PyTorch多GPU离线推理速度优化咨询:3000万样本推理耗时超限及DataParallel未达预期加速问题
离线PyTorch模型推理加速方案
嘿,我来帮你搞定这3000万样本的推理提速问题!你现在用nn.DataParallel没达到4倍速,再加上单样本循环的方式,完全浪费了GPU的并行算力,咱们一步步来优化:
一、先解决最核心的问题:从单样本推理改成批量推理
GPU天生就是为并行处理批量数据设计的,你现在每次只喂一个样本,GPU的计算单元根本跑不满——这才是耗时的关键!单样本30ms,换成批量比如64个样本,总耗时可能只需要50ms左右(远小于64×30ms),直接把整体效率拉上去一个档次。
修改代码的思路:
- 先把读取的样本攒成一个batch,比如每次收集N个样本再一起预处理、推理
- 注意保证batch内的样本维度一致(比如输入张量的shape要统一)
示例代码片段:
import torch from torch.utils.data import Dataset, DataLoader # 自定义数据集类,处理你的文本样本 class MyDataset(Dataset): def __init__(self, file_path): self.lines = [line.strip() for line in open(file_path, "r")] def __len__(self): return len(self.lines) def __getitem__(self, idx): # 这里写你的单样本预处理逻辑,返回模型需要的张量 return preprocess(self.lines[idx]) # 初始化数据集和DataLoader,用多进程加载预处理数据 dataset = MyDataset("only-one-file") dataloader = DataLoader(dataset, batch_size=128, num_workers=8, shuffle=False) # 推理循环 model.eval() with torch.no_grad(): for batch in dataloader: batch = batch.cuda() # 后续换DDP的话要注意设备分配 results = model(batch) # 处理results,比如打印或者保存 for result in results: print(result)
二、替换DataParallel为DistributedDataParallel(DDP)
nn.DataParallel是单进程多GPU模式,主进程要负责把数据分发到各个GPU、收集结果,通信开销特别大——尤其是小batch的时候,这就是你没达到4倍速的主要原因。而DDP是多进程多GPU,每个GPU对应一个独立进程,通信效率高得多,能更接近线性加速比。
修改步骤:
- 用
torch.distributed初始化进程组 - 每个进程加载自己的模型副本,分配到对应的GPU
- 用DDP包装模型
示例代码框架:
import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP def main(): # 初始化进程组 dist.init_process_group(backend='nccl') local_rank = dist.get_local_rank() torch.cuda.set_device(local_rank) # 加载模型 model = Model(*******************) model = model.cuda(local_rank) model = DDP(model, device_ids=[local_rank]) model.load_state_dict(torch.load(model_path, map_location=f'cuda:{local_rank}')) model.eval() # 用DDP对应的DataLoader(需要设置分布式sampler) dataset = MyDataset("only-one-file") sampler = torch.utils.data.distributed.DistributedSampler(dataset) dataloader = DataLoader(dataset, batch_size=128, num_workers=8, sampler=sampler) # 推理循环 with torch.no_grad(): for batch in dataloader: batch = batch.cuda(local_rank) results = model(batch) # 处理结果 dist.destroy_process_group() if __name__ == "__main__": main()
运行的时候需要用torchrun启动:torchrun --nproc_per_node=4 your_script.py,这样会自动分配4个进程对应你的4块GPU。
三、其他辅助优化手段
- 模型量化/脚本化:用
torch.jit.trace或者torch.jit.script把模型转成TorchScript,减少Python运行时开销;或者用torch.ao.quantization做INT8量化,能大幅降低计算量,提升推理速度,同时精度损失很小。 - 检查GPU利用率:用
nvidia-smi或者torch.cuda.utilization()看看GPU是不是没跑满,如果利用率低,大概率是CPU预处理拖了后腿,那就要加大num_workers,或者把预处理逻辑用Cython/Numba加速。 - 数据预加载:如果样本是文本,可以先把所有预处理好的张量保存成二进制文件(比如用torch.save),推理的时候直接加载张量,省去重复预处理的时间。
为什么你现在的DataParallel没到4倍速?
因为DataParallel的单进程架构,每次推理都要把数据从主进程拷贝到各个GPU,推理完再把结果拷贝回来——单样本的时候,拷贝的时间甚至比推理时间还长,自然没法达到线性加速。换成批量+DDP之后,通信开销占比会大幅降低,就能接近4倍的速度了。
内容的提问来源于stack exchange,提问作者Lucky Ning
相关产品推荐
相关产品推荐

