当前位置: 首页 > news >正文

网站甚而模板手机网站样式

网站甚而模板,手机网站样式,网站建设 前沿文章,嘉禾县网站建设推广公司1 模型并行化训练 1.1 为什么要并行训练 在训练大型数据集或者很大的模型时一块GPU很难放下#xff0c;例如最初的AlexNet就是在两块GPU上计算的。并行计算一般采取两个策略#xff1a;一个是模型并行#xff0c;一个是数据并行。左图中是将模型的不同部分放在不同GPU上进…1 模型并行化训练 1.1 为什么要并行训练 在训练大型数据集或者很大的模型时一块GPU很难放下例如最初的AlexNet就是在两块GPU上计算的。并行计算一般采取两个策略一个是模型并行一个是数据并行。左图中是将模型的不同部分放在不同GPU上进行训练最后汇总计算。而右图中是将数据放在不同GPU上进行训练最后汇总计算不仅能增大BatchSize还能加快计算速度提高计算精度 1.2 并行化训练策略 并行化深度学习模型有两种流行的方式模型并行和数据并行 模型并行 模型并行性是指模型在逻辑上分为几个部分即一个部分中的某些层而另一部分中的某些层然后将其放置在不同的硬件/设备上。尽管将零件放在不同的设备上确实在执行时间数据的异步处理方面有很多好处但通常可以采用它来避免内存限制。具有大量参数的模型由于这种类型的策略而受益这些模型由于内存占用量大而难以放入单个系统中。 数据并行 另一方面数据并行性是指通过位于不同硬件/设备上的同一网络的多个副本来处理多段数据技术上为批次。与模型并行性不同每个副本可能是整个网络而不仅仅是一部分。这种策略可以随着数据量的增加而很好地扩展。但是由于整个网络必须驻留在单个设备上因此无法帮助占用大量内存的模型。 1.3 单机多卡与多级多卡 在深度学习和其他高性能计算任务中单机多卡Single-Node Multi-GPU和多机多卡Multi-Node Multi-GPU是两种常见的硬件配置它们涉及使用多个图形处理单元GPUs来加速计算。单机多卡配置通常更容易管理和维护而多机多卡配置提供了更高的计算能力和扩展性但也带来了更高的复杂度和成本。 2.1.1 单机多卡 (Single-Node Multi-GPU) 定义所有的 GPU 都安装在同一台机器上。 通信GPU之间通过PCIe总线或者更高带宽的NVLink进行通信。 适用性适合中等规模的数据集和模型通常用于实验室环境或小规模的商业应用。 设置复杂度相对简单因为所有的通信都在一个节点内部进行。 扩展性受限于单个节点能够支持的最大GPU数量。 示例场景在一个数据中心的单个服务器上训练深度学习模型。 2.1.2 多机多卡 (Multi-Node Multi-GPU) 定义GPU 分布在多台机器上这些机器通过网络连接。 通信机器之间的通信通过高速网络例如InfiniBand进行但比单节点内部的通信要慢。 适用性适合大规模数据集和模型通常用于大型数据中心或复杂的机器学习任务。 设置复杂度更复杂需要管理节点间的网络通信和同步。 扩展性理论上可以通过增加更多节点来无限扩展。 示例场景在多个数据中心分布的服务器上训练大型深度学习模型如训练大型语言模型或复杂的科学计算任务。 2 使用DistributedDataParallel实现模型并行化训练 2.1 基本概念 DistributedDataParallel中的关键概念 训练过程示意如下 分布式训练的启动有两种方法一种是torch.multiprocessing还有一种是torch.distributed 第一种在启动程序时不需要在命令行输入额外的参数写起来也比较容易但是调试较麻烦比如MAE第二种必须要用命令行启动写起来略微复杂但是调试较方便。 2.2 torch.distributed分布式训练步骤 2.2.1 导入分布式模块 其中distributed中必须导入的是以下模块 import torch.distributed as dist 2.2.2 用argparse编写模型的个性化参数 parser argparse.ArgumentParser() ...your params ...distributed params# 开启的进程数不用设置该参数会根据nproc_per_node自动设置 parser.add_argument(--world-size, default4, typeint, helpnumber of distributed processes) parser.add_argument(--local_rank, typeint, helprank of distributed processes) opt parser.parse_args()注意这里如果使用了argparse方法的话必须传入local_rank参数系统会自动给他进行赋值如果不传入会报错  2.2.3 初始化distributed 初始化过程如下假设我们的world_size8那么我们有8张GPU初始化初始化有快有慢快的GPU初始化会在dist.barrier()处停下来等待当所有的GPU都到达这个函数时才会继续运行之后的代码。 # 初始化各进程环境 if RANK in os.environ and WORLD_SIZE in os.environ:args.rank int(os.environ[RANK])args.world_size int(os.environ[WORLD_SIZE])args.gpu int(os.environ[LOCAL_RANK]) else:print(Not using distributed mode)return# 设置当前程序使用的GPU。根据python的机制在单卡训练时本质上程序只使用一个CPU核心而DataParallel # 不管用了几张GPU依然只用一个CPU核心在分布式训练中每一张卡分别对应一个CPU核心即几个GPU几个CPU核心 torch.cuda.set_device(args.gpu)# 分布式初始化 args.dist_url env:// # 设置url args.dist_backend nccl # 通信后端nvidia GPU推荐使用NCCL print(| distributed init (rank {}): {}.format(args.rank, args.dist_url), flushTrue) dist.init_process_group(backendargs.dist_backend, init_methodargs.dist_url, world_sizeargs.world_size, rankargs.rank) dist.barrier() # 等待所有进程都初始化完毕即所有GPU都要运行到这一步以后在继续 | distributed init (rank 1): env:// | distributed init (rank 2): env:// | distributed init (rank 0): env:// | distributed init (rank 3): env://torch.distributed.init_process_group 是PyTorch中的一个函数它用于初始化默认的分布式进程组从而允许进行跨多个进程的通信。这个函数在使用 PyTorch 的分布式功能时非常重要特别是在使用 DistributedDataParallel (DDP) 进行多GPU或多节点训练时。真正意义上来讲分布式的初始化就只有dist.init_process_group这一句。 从上面我们print的输出可以得到不同GPUs初始化的速度是不同的这也正是因为每个GPU都分配了一个CPU核心他们的速度有快有慢比如本次实验初始化顺序为1203 关于环境变量有一下几点需要注意 local_rank是被自动赋值的在单机多卡中他和rank的值相同os.environ[“RANK”]是没有值的运行时在命令行上输入python -m torch.distributed.launch --nproc_per_node4 --use_env train.py他才被赋予了值–nproc_per_node4这条指令可以将os.environ[“WORLD_SIZE”]赋值为4 如果用argparse这个库就必须加上local_rank变量如果忘记加了在命令行启动时就需要加上–use_env参数–use_env 表示 Local Rank 用 LOCAL_RANK 这个环境变量传参 2.2.4 设置数据集分布式的数据集加载 设置数据集分布式的数据集加载不同于之前的单卡这里需要将数据集分为N部分N为卡的数量。单卡时只需要设置Datasets→DataLoader即可但是分布式中需要对每一块GPU分配不重复的数据分配方式也不难分配方式变为Datasets→DistributedSampler→BatchSampler→DataLoaderBatchSampler可以省略 DistributedSampler将数据集N等分BatchSamper将每一等分后的数据内部进行batch的划分。BatchSampler的作用就是分配batchsize这一步可以再DataLoader中分配因此也可以将BatchSampler省略。下图展示了数据集的分配过程 # 1. datasets train_datasets MyDataSet(xxx) val_datasets MyDataSet(xxx)# 2. DistributedSampler # 给每个rank对应的进程分配训练的样本索引比如一共800样本8张卡那么每张卡对应分配100个样本 train_sampler torch.utils.data.distributed.DistributedSampler(train_datasets) val_sampler torch.utils.data.distributed.DistributedSampler(val_datasets)# 3. BatchSampler # 刚才每张卡分了100个样本假设BatchSize16那么能分成100/166...4即多出4个样本 # 下面的drop_lastTrue表示舍弃这四个样本False将剩余4个样本为一组注意最后就不是6个一组了 train_batch_sampler torch.utils.data.BatchSampler(train_sampler, batch_size, drop_lastTrue)# 4. DataLoader # 验证集没有采用batchsampler,因此在dataloader中使用batch_size参数即可 train_dataloader torch.utils.data.DataLoader(train_datasets,batch_samplertrain_batch_sampler, pin_memoryTrue, num_workersnw) val_dataloader torch.utils.data.DataLoader(val_datasets,batch_sizebatch_size, samplerval_sampler, pin_memoryTrue, num_workersnw) 2.2.5 加载模型到所有GPUs上 在训练时因为我们用到了DistributedSampler所以需要每一个epoch都将原数据打乱一下其他剩下的过程和单卡相同 model UNet().cuda() model torch.nn.parallel.DistributedDataParallel(model, device_ids[rank]) ...for epoch in range(start_epoch, n_epochs):if is_distributed:train_sampler.set_epoch(epoch)... 2.2.6 启动分布式训练 python -m torch.distributed.launch --nproc_per_node4 --master_port2424 --use_env main.py (your_argparse_params) 在pytorch新版中将python -m torch.distributed.launch替换为了torchrun在训练时我们需要指定通讯端口master_port也可以让程序自动寻找即将--master_portxxxx替换为--rdzv_backend c10d --master_port0   2.3 torch.multiprocessing分部署训练步骤 通过核心函数spawn函数调用GPU并行函数的参数如下 torch.multiprocessing.spawn(fn, args(), nprocs1, joinTrue, daemonFalse, start_methodspawn) fn这个就是我们要分布式运行的函数一般来说是main函数main(rank, *args)其中rank为必须单机多卡中可以理解为第几个GPUargs为函数传入的参数类型tuple在spawn(…args)的args参数中定义args传入fn的参数tuplenprocs进程数即几张卡join: 默认为True即可daemon: 默认为False即可 # 调用 mp.spawn(main, args(opt, ), nprocsopt.world_size, joinTrue) 与distributed大同小异完整的训练代码如下 # 单机多卡并行计算示例 import os os.environ[CUDA_VISIBLE_DEVICES] 6, 7import torch import torch.distributed as dist import torch.multiprocessing as mp import torch.nn as nn import torch.optim as optim from torch.nn.parallel import DistributedDataParallel as DDPdef example(rank, world_size):# create default process groupdist.init_process_group(gloo, init_methodtcp://127.0.0.1:6666, rankrank, world_sizeworld_size)# create local modelmodel nn.Linear(10, 10).to(rank)# construct DDP modelddp_model DDP(model, device_ids[rank])# define loss function and optimizerloss_fn nn.MSELoss()optimizer optim.SGD(ddp_model.parameters(), lr0.001)# forward passoutputs ddp_model(torch.randn(20, 10).to(rank))labels torch.randn(20, 10).to(rank)# backward passloss_fn(outputs, labels).backward()# update parametersoptimizer.step()print(finished rank: {}.format(rank))def main():world_size torch.cuda.device_count()mp.spawn(example,args(world_size,),nprocsworld_size,joinTrue)if __name____main__:main() 2.4 dist.barrier()函数  单机多卡环境下使用分布式训练具有更快的速度。PyTorch在分布式训练过程中对于数据的读取是采用主进程预读取并缓存然后其它进程从缓存中读取不同进程之间的数据同步具体通过torch.distributed.barrier()实现示例如下 if args.local_rank not in [-1, 0]:torch.distributed.barrier() # Make sure only the first process in distributed training will download model vocab... (loads the model and the vocabulary)if args.local_rank 0:torch.distributed.barrier() # Make sure only the first process in distributed training will download model vocab 假设我们有4张卡[0, 1, 2, 3]其中[0]卡是first process或者base process有些操作不需要所有的卡同时进行比如在预处理的时候只用base process即可。 在上述代码中第一个if是说除了主卡之外的卡运行到此处会被barrier也就是说运行到这里就停止了而base process不会停止会继续运行执行预加载模型等操作当主卡运行到第二个if时他也会进入到barrier就是说他已经预加载完了现在他也需要被barrier了。 此时所有的卡都进入到了barrier意味着所有的卡可以继续运行主卡已经加载完了这个数据所有的卡都可以使用此后所有的卡从barrier撤出开始执行训练。 a process is blocked by a barrier until all processes have encountered a barrier, upon which the barrier is lifted for all processes3 一个完整的例子 3.1 初始化进程组 import os from torch import distributedtry:world_size int(os.environ[WORLD_SIZE]) # 全局进程个数rank int(os.environ[RANK]) # 当前进程编号(全局)local_rank int(os.environ[LOCAL_RANK]) # 每台机器上的进程编号(局部)distributed.init_process_group(nccl) # 初始化进程, 使用nccl后端 except KeyError:world_size 1rank 0local_rank 0distributed.init_process_group(backendnccl,init_methodtcp://127.0.0.1:12584,rankrank,world_sizeworld_size,) 3.2 使用DistributedSampler划分数据集 与nn.DataParrallel不同的是分布式训练中的batch_size为单卡的输入样本数因为它代表的是当前rank下对应的partition总batch_size是这里的batch_size再乘以并行数。举个例子假设使用8张卡训练模型nn.DataParrallel中的batch_size为3200nn.DistributedDataParallel中的batch_size则为400。 from dataloader.distributed_sampler import DistributedSamplertrain_sampler DistributedSampler(train_set, num_replicasworld_size, rankrank, shuffleTrue, seedseed) trainloader DataLoader(datasettrain_set,pin_memorytrue,batch_sizebatch_size,num_workersnum_workers,samplertrain_sampler ) # pin_memory: 是否提前申请CUDA内存. 创建DataLoader时设置pin_memoryTrue则意味着生成的Tensor数据最开始是属于内存中的锁页内存这样将内存的Tensor转义到GPU的显存就会更快一些. 3.3 使用DistributedDataParallel封装模型 DistributedDataParallel能够为不同GPU上求得的梯度进行all reduce(即汇总不同GPU计算所得的梯度并同步计算结果)。all reduce后不同GPU中模型的梯度均为all reduce之前各GPU梯度的均值。 backbone get_model(cfg.network, dropout0.0, fp16cfg.fp16, num_featurescfg.embedding_size).cuda()backbone torch.nn.parallel.DistributedDataParallel(modulebackbone, broadcast_buffersFalse, device_ids[local_rank], bucket_cap_mb16,find_unused_parametersTrue) 3.4 训练模型 把输入图片、标签及模型加载到当前进程使用的GPU中 for epoch in range(start_epoch, cfg.num_epoch):if isinstance(train_loader, DataLoader):# 设置train_loader中的sampler的epochDistributedSampler需要这个参数来维持各个进程之间的相同随机数种子train_loader.sampler.set_epoch(epoch)for _, (img, local_labels) in enumerate(train_loader):global_step 1local_embeddings backbone(img)loss: torch.Tensor module_partial_fc(local_embeddings, local_labels, opt)loss.backward()torch.nn.utils.clip_grad_norm_(backbone.parameters(), 5)opt.step()opt.zero_grad()lr_scheduler.step() 3.5 计算损失 distributed.all_gather(tensor_listinput_tensor)从所有设备收集指定的input_tensor并将其放置在所有设备上的tensor_list变量中 from torch import distributeddistributed.all_gather(_gather_embeddings, local_embeddings) distributed.all_gather(_gather_labels, local_labels)distributed.all_reduce(loss, distributed.ReduceOp.SUM) 3.6 保存模型 if rank 0:path_module os.path.join(cfg.output, model_final.pt)torch.save(backbone.module.state_dict(), path_module) 3.7 启动并行程序 (1) 使用torch.distributed.launch 该指令会使脚本并行地运行n次(n为使用的GPU个数) python -m torch.distributed.launch --nproc_per_node8 train.py configs/ms1mv3_r50 (2) 使用torch.multiprocessing torch.multiprocessing会自动创建进程绕开torch.distributed.launch开启和退出进程的一些小毛病 def main(rank):passtorch.multiprocessing.spawn(main, nprocs, args) 3.8 完整代码 import argparse import logging import os from datetime import datetimeimport numpy as np import torch from backbones import get_model from dataset import get_dataloader from losses import CombinedMarginLoss from lr_scheduler import PolyScheduler from partial_fc import PartialFC, PartialFCAdamW from torch import distributed from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter from utils.utils_callbacks import CallBackLogging, CallBackVerification from utils.utils_config import get_config from utils.utils_distributed_sampler import setup_seed from utils.utils_logging import AverageMeter, init_loggingassert torch.__version__ 1.12.0, In order to enjoy the features of the new torch, \ we have upgraded the torch to 1.12.0. torch before than 1.12.0 may not work in the future.try:rank int(os.environ[RANK])local_rank int(os.environ[LOCAL_RANK])world_size int(os.environ[WORLD_SIZE])distributed.init_process_group(nccl) except KeyError:rank 0local_rank 0world_size 1distributed.init_process_group(backendnccl,init_methodtcp://127.0.0.1:12584,rankrank,world_sizeworld_size,)def main(args):# get configcfg get_config(args.config)# global control random seedsetup_seed(seedcfg.seed, cuda_deterministicFalse)torch.cuda.set_device(local_rank)os.makedirs(cfg.output, exist_okTrue)init_logging(rank, cfg.output)summary_writer (SummaryWriter(log_diros.path.join(cfg.output, tensorboard))if rank 0else None)wandb_logger Noneif cfg.using_wandb:import wandb# Sign in to wandbtry:wandb.login(keycfg.wandb_key)except Exception as e:print(WandB Key must be provided in config file (base.py).)print(fConfig Error: {e})# Initialize wandbrun_name datetime.now().strftime(%y%m%d_%H%M) f_GPU{rank}run_name run_name if cfg.suffix_run_name is None else run_name f_{cfg.suffix_run_name}try:wandb_logger wandb.init(entity cfg.wandb_entity, project cfg.wandb_project, sync_tensorboard True,resumecfg.wandb_resume,name run_name, notes cfg.notes) if rank 0 or cfg.wandb_log_all else Noneif wandb_logger:wandb_logger.config.update(cfg)except Exception as e:print(WandB Data (Entity and Project name) must be provided in config file (base.py).)print(fConfig Error: {e})train_loader get_dataloader(cfg.rec,local_rank,cfg.batch_size,cfg.dali,cfg.seed,cfg.num_workers)backbone get_model(cfg.network, dropout0.0, fp16cfg.fp16, num_featurescfg.embedding_size).cuda()backbone torch.nn.parallel.DistributedDataParallel(modulebackbone, broadcast_buffersFalse, device_ids[local_rank], bucket_cap_mb16,find_unused_parametersTrue)backbone.train()# FIXME using gradient checkpoint if there are some unused parameters will cause errorbackbone._set_static_graph()margin_loss CombinedMarginLoss(64,cfg.margin_list[0],cfg.margin_list[1],cfg.margin_list[2],cfg.interclass_filtering_threshold)if cfg.optimizer sgd:module_partial_fc PartialFC(margin_loss, cfg.embedding_size, cfg.num_classes,cfg.sample_rate, cfg.fp16)module_partial_fc.train().cuda()# TODO the params of partial fc must be last in the params listopt torch.optim.SGD(params[{params: backbone.parameters()}, {params: module_partial_fc.parameters()}],lrcfg.lr, momentum0.9, weight_decaycfg.weight_decay)elif cfg.optimizer adamw:module_partial_fc PartialFCAdamW(margin_loss, cfg.embedding_size, cfg.num_classes,cfg.sample_rate, cfg.fp16)module_partial_fc.train().cuda()opt torch.optim.AdamW(params[{params: backbone.parameters()}, {params: module_partial_fc.parameters()}],lrcfg.lr, weight_decaycfg.weight_decay)else:raisecfg.total_batch_size cfg.batch_size * world_sizecfg.warmup_step cfg.num_image // cfg.total_batch_size * cfg.warmup_epochcfg.total_step cfg.num_image // cfg.total_batch_size * cfg.num_epochlr_scheduler PolyScheduler(optimizeropt,base_lrcfg.lr,max_stepscfg.total_step,warmup_stepscfg.warmup_step,last_epoch-1)start_epoch 0global_step 0if cfg.resume:dict_checkpoint torch.load(os.path.join(cfg.output, fcheckpoint_gpu_{rank}.pt))start_epoch dict_checkpoint[epoch]global_step dict_checkpoint[global_step]backbone.module.load_state_dict(dict_checkpoint[state_dict_backbone])module_partial_fc.load_state_dict(dict_checkpoint[state_dict_softmax_fc])opt.load_state_dict(dict_checkpoint[state_optimizer])lr_scheduler.load_state_dict(dict_checkpoint[state_lr_scheduler])del dict_checkpointfor key, value in cfg.items():num_space 25 - len(key)logging.info(: key * num_space str(value))callback_verification CallBackVerification(val_targetscfg.val_targets, rec_prefixcfg.rec, summary_writersummary_writer, wandb_logger wandb_logger)callback_logging CallBackLogging(frequentcfg.frequent,total_stepcfg.total_step,batch_sizecfg.batch_size,start_step global_step,writersummary_writer)loss_am AverageMeter()amp torch.cuda.amp.grad_scaler.GradScaler(growth_interval100)for epoch in range(start_epoch, cfg.num_epoch):if isinstance(train_loader, DataLoader):train_loader.sampler.set_epoch(epoch)for _, (img, local_labels) in enumerate(train_loader):global_step 1local_embeddings backbone(img)loss: torch.Tensor module_partial_fc(local_embeddings, local_labels, opt)if cfg.fp16:amp.scale(loss).backward()amp.unscale_(opt)torch.nn.utils.clip_grad_norm_(backbone.parameters(), 5)amp.step(opt)amp.update()else:loss.backward()torch.nn.utils.clip_grad_norm_(backbone.parameters(), 5)opt.step()opt.zero_grad()lr_scheduler.step()with torch.no_grad():if wandb_logger:wandb_logger.log({Loss/Step Loss: loss.item(),Loss/Train Loss: loss_am.avg,Process/Step: global_step,Process/Epoch: epoch})loss_am.update(loss.item(), 1)callback_logging(global_step, loss_am, epoch, cfg.fp16, lr_scheduler.get_last_lr()[0], amp)if global_step % cfg.verbose 0 and global_step 0:callback_verification(global_step, backbone)if cfg.save_all_states:checkpoint {epoch: epoch 1,global_step: global_step,state_dict_backbone: backbone.module.state_dict(),state_dict_softmax_fc: module_partial_fc.state_dict(),state_optimizer: opt.state_dict(),state_lr_scheduler: lr_scheduler.state_dict()}torch.save(checkpoint, os.path.join(cfg.output, fcheckpoint_gpu_{rank}.pt))if rank 0:path_module os.path.join(cfg.output, model.pt)torch.save(backbone.module.state_dict(), path_module)if wandb_logger and cfg.save_artifacts:artifact_name f{run_name}_E{epoch}model wandb.Artifact(artifact_name, typemodel)model.add_file(path_module)wandb_logger.log_artifact(model)if cfg.dali:train_loader.reset()if rank 0:path_module os.path.join(cfg.output, model.pt)torch.save(backbone.module.state_dict(), path_module)from torch2onnx import convert_onnxconvert_onnx(backbone.module.cpu().eval(), path_module, os.path.join(cfg.output, model.onnx))if wandb_logger and cfg.save_artifacts:artifact_name f{run_name}_Finalmodel wandb.Artifact(artifact_name, typemodel)model.add_file(path_module)wandb_logger.log_artifact(model)distributed.destroy_process_group()if __name__ __main__:torch.backends.cudnn.benchmark Trueparser argparse.ArgumentParser(descriptionDistributed Arcface Training in Pytorch)parser.add_argument(config, typestr, helppy config file)main(parser.parse_args()) 4 分布式训练可能遇到的问题 4.1 runtimeerror: address already in use 这种情况是端口被占用了可能是由于你上次调试之后端口依旧占用的缘故假设88889端口被占用了用以下命令查询其PID然后杀掉即可。第二种方法是将当前终端关闭重新开一个他会自动解除占用 4.2 调试时可能会出现的问题 显存未释放nvidia-smi看一下显存是否释放如果没有释放使用kill -9 PID命令进行释放。如果kill也无法释放显存直接将terminal关闭重新开一个即可端口被占用如果第一次调试后进行第二次调试时提示xx端口被占用了这里最快的解决方法时将当前terminal关闭然后重新开一个即可或者参考第一个问题kill掉相应的PID
文章转载自:
http://www.morning.ishoufeipin.cn.gov.cn.ishoufeipin.cn
http://www.morning.ykshx.cn.gov.cn.ykshx.cn
http://www.morning.mxdhy.cn.gov.cn.mxdhy.cn
http://www.morning.kdlzz.cn.gov.cn.kdlzz.cn
http://www.morning.dqkcn.cn.gov.cn.dqkcn.cn
http://www.morning.gyylt.cn.gov.cn.gyylt.cn
http://www.morning.pxrfm.cn.gov.cn.pxrfm.cn
http://www.morning.gjqwt.cn.gov.cn.gjqwt.cn
http://www.morning.qbrdg.cn.gov.cn.qbrdg.cn
http://www.morning.bnmfq.cn.gov.cn.bnmfq.cn
http://www.morning.xknsn.cn.gov.cn.xknsn.cn
http://www.morning.rmfh.cn.gov.cn.rmfh.cn
http://www.morning.itvsee.com.gov.cn.itvsee.com
http://www.morning.khlxd.cn.gov.cn.khlxd.cn
http://www.morning.xkhxl.cn.gov.cn.xkhxl.cn
http://www.morning.lsfzq.cn.gov.cn.lsfzq.cn
http://www.morning.qxlhj.cn.gov.cn.qxlhj.cn
http://www.morning.jwtjf.cn.gov.cn.jwtjf.cn
http://www.morning.prgdy.cn.gov.cn.prgdy.cn
http://www.morning.wkkqw.cn.gov.cn.wkkqw.cn
http://www.morning.krqhw.cn.gov.cn.krqhw.cn
http://www.morning.rfxg.cn.gov.cn.rfxg.cn
http://www.morning.rkzk.cn.gov.cn.rkzk.cn
http://www.morning.zpqk.cn.gov.cn.zpqk.cn
http://www.morning.gwyml.cn.gov.cn.gwyml.cn
http://www.morning.zrgx.cn.gov.cn.zrgx.cn
http://www.morning.xxhc.cn.gov.cn.xxhc.cn
http://www.morning.mwlxk.cn.gov.cn.mwlxk.cn
http://www.morning.chmkt.cn.gov.cn.chmkt.cn
http://www.morning.mqzcn.cn.gov.cn.mqzcn.cn
http://www.morning.yhpq.cn.gov.cn.yhpq.cn
http://www.morning.woyoua.com.gov.cn.woyoua.com
http://www.morning.wxfgg.cn.gov.cn.wxfgg.cn
http://www.morning.bxyzr.cn.gov.cn.bxyzr.cn
http://www.morning.cjnfb.cn.gov.cn.cjnfb.cn
http://www.morning.thbqp.cn.gov.cn.thbqp.cn
http://www.morning.drbd.cn.gov.cn.drbd.cn
http://www.morning.ntyks.cn.gov.cn.ntyks.cn
http://www.morning.wsgyq.cn.gov.cn.wsgyq.cn
http://www.morning.hzryl.cn.gov.cn.hzryl.cn
http://www.morning.kxymr.cn.gov.cn.kxymr.cn
http://www.morning.jzykw.cn.gov.cn.jzykw.cn
http://www.morning.zwgbz.cn.gov.cn.zwgbz.cn
http://www.morning.cwknc.cn.gov.cn.cwknc.cn
http://www.morning.jtfcd.cn.gov.cn.jtfcd.cn
http://www.morning.snzgg.cn.gov.cn.snzgg.cn
http://www.morning.dfkmz.cn.gov.cn.dfkmz.cn
http://www.morning.zdzgf.cn.gov.cn.zdzgf.cn
http://www.morning.ygztf.cn.gov.cn.ygztf.cn
http://www.morning.2d1bl5.cn.gov.cn.2d1bl5.cn
http://www.morning.ummpdl.cn.gov.cn.ummpdl.cn
http://www.morning.ksgjy.cn.gov.cn.ksgjy.cn
http://www.morning.bflwj.cn.gov.cn.bflwj.cn
http://www.morning.bnylg.cn.gov.cn.bnylg.cn
http://www.morning.dwmmf.cn.gov.cn.dwmmf.cn
http://www.morning.cjmmn.cn.gov.cn.cjmmn.cn
http://www.morning.llxqj.cn.gov.cn.llxqj.cn
http://www.morning.zpyh.cn.gov.cn.zpyh.cn
http://www.morning.tsnq.cn.gov.cn.tsnq.cn
http://www.morning.yfrlk.cn.gov.cn.yfrlk.cn
http://www.morning.wjtxt.cn.gov.cn.wjtxt.cn
http://www.morning.pshtf.cn.gov.cn.pshtf.cn
http://www.morning.rfwkn.cn.gov.cn.rfwkn.cn
http://www.morning.hbkkc.cn.gov.cn.hbkkc.cn
http://www.morning.lqgfm.cn.gov.cn.lqgfm.cn
http://www.morning.xrwsg.cn.gov.cn.xrwsg.cn
http://www.morning.nwmwp.cn.gov.cn.nwmwp.cn
http://www.morning.rgpbk.cn.gov.cn.rgpbk.cn
http://www.morning.jqjnx.cn.gov.cn.jqjnx.cn
http://www.morning.bmmhs.cn.gov.cn.bmmhs.cn
http://www.morning.wqtzs.cn.gov.cn.wqtzs.cn
http://www.morning.qbnfc.cn.gov.cn.qbnfc.cn
http://www.morning.qfkdt.cn.gov.cn.qfkdt.cn
http://www.morning.lqytk.cn.gov.cn.lqytk.cn
http://www.morning.bpmtq.cn.gov.cn.bpmtq.cn
http://www.morning.crxdn.cn.gov.cn.crxdn.cn
http://www.morning.twmp.cn.gov.cn.twmp.cn
http://www.morning.rkrcd.cn.gov.cn.rkrcd.cn
http://www.morning.cpktd.cn.gov.cn.cpktd.cn
http://www.morning.zffn.cn.gov.cn.zffn.cn
http://www.tj-hxxt.cn/news/282132.html

相关文章:

  • 南通网站建设解决方案做网站的标签什么意思
  • 阿里云建设网站好吗wp网站模板
  • 南京平面设计师联盟外贸网站seo怎么做
  • 青岛网站建设哪里好广州企业建站模板
  • 网站域名响应时间中国最受欢迎的网站
  • 如何使用qq空间做推广网站网站开发项目意义
  • 太原网站搭建推广成熟网站开发联系电话
  • 网站关键词数量广东省自然资源厅地址电话
  • 网站开发的相关技能有哪些大学生自学网
  • 上海有名的网站建设公司陕西网站备案代理
  • 网站建设的需求客户企业信用网
  • 安卓市场网站建设健康河北app下载二维码
  • 给别人做网站怎么赚钱百度官方平台
  • 西安网站制作推广wordpress标签打不开
  • 网站被墙了怎么办wordpress编辑远程图片
  • 在线音乐播放网站模板买域名价格
  • 做网站的如何增加电话量文学网站开发
  • 宜昌小学网站建设寮步网站建设公司
  • 做网站投注员挣钱吗c 网站开发引擎
  • 淘宝客网站需要备案吗中山有哪些网站建立公司
  • 免费商用自媒体图片网站网站点内页还是首页
  • 建设安全协会网站招投标网站开发
  • 如何快速备案网站网站更新维护 怎么做
  • 中小企业网站建设 网络营销番禺人才网最新招聘信息网
  • 沈阳个人网站制作网站优化的要求
  • 抚顺网站建设推荐快速建站系统
  • 湛江网站制作推荐加强政务公开网站建设
  • 企业网站背景颜色做国外衣服的网站
  • 河南省汝州市文明建设网站南昌网站建设兼职
  • 建筑类专业做教育的网站Python视频直播网站开发