You need to enable JavaScript to run this app. Colab中如何用subprocess实现YOLOv4的GPU并发批量推理
优惠活动
大模型
产品
解决方案
定价
更多

Colab中如何用subprocess实现YOLOv4的GPU并发批量推理

YOLOv4 Darknet 批量推理优化方案(Colab + Tesla V100)

原有逐张循环调用Darknet检测命令的流程,存在大量无效开销:每次启动独立进程都要重新加载YOLOv4权重、初始化CUDA上下文,单张推理时Tesla V100的显存、算力利用率通常不足10%,大规模测试集下90%的时间都消耗在重复的进程初始化上,而非实际推理。

优先方案:Darknet原生批量推理(零额外并发开销)

绝大多数支持CUDA编译的Darknet版本,都原生支持通过路径列表批量处理图片,无需自行管理并发,仅需启动一次进程、加载一次权重即可跑完所有测试图,速度是逐张调用的10~20倍。

实现步骤:

  • 收集所有测试目录下的PNG图片绝对路径,写入临时列表文件
  • 单次调用Darknet命令传入列表参数,批量完成所有推理
  • 代码示例:
import os
import glob
import subprocess

# 测试图目录配置
TEST_IMG_DIR = "/content/darknet/test_images"
# 收集所有PNG路径
test_imgs = sorted(glob.glob(os.path.join(TEST_IMG_DIR, "*.png")))

# 生成Darknet可读取的路径列表文件
with open("test_imgs_list.txt", "w") as f:
    f.write("\n".join(test_imgs))

# 单次调用Darknet完成全量推理
darknet_cmd = [
    "./darknet", "detector", "test",
    "cfg/obj.data", "cfg/yolov4-custom.cfg", "backup/yolov4-custom_last.weights",
    "-list", "test_imgs_list.txt",
    "-thresh", "0.5",
    "-ext_output", # 输出检测框坐标
    "-dont_show", # 跳过可视化渲染,无需要保存检测图时加这个参数提速30%
    "-out", "detection_results.json" # 结果统一输出到json
]
subprocess.run(darknet_cmd, check=True)

备选方案:Subprocess受控并发(适配不支持列表参数的旧版Darknet)

如果使用的Darknet版本没有原生-list参数,可通过拆分任务、多进程并发的方式提升利用率,Tesla V100 16G显存下单YOLOv4 416输入的推理进程仅占用1.5G显存,可同时开34个并发进程不会触发OOM。

实现步骤:

  • 拆分全量测试图为多个小批次,每个批次对应一个独立的Darknet子进程
  • 用进程池管理并发数量,避免显存过载
  • 代码示例:
import os
import glob
import subprocess
from concurrent.futures import ProcessPoolExecutor

# 环境适配参数
TEST_IMG_DIR = "/content/darknet/test_images"
BATCH_SIZE_PER_WORKER = 20 # 单个子进程一次处理20张图,减少循环调用
MAX_WORKERS = 3 # 16G V100适配3个并发,32G显存可调整为5

# 拆分全量列表为小批次
def split_list(lst, batch_size):
    for i in range(0, len(lst), batch_size):
        yield lst[i:i+batch_size]

# 单个子进程的推理任务
def run_darknet_single_batch(img_batch):
    tmp_list = f"/tmp/batch_{os.getpid()}.txt"
    with open(tmp_list, "w") as f:
        f.write("\n".join(img_batch))
    
    cmd = [
        "./darknet", "detector", "test",
        "cfg/obj.data", "cfg/yolov4-custom.cfg", "backup/yolov4-custom_last.weights",
        tmp_list, # 旧版Darknet直接传入单批次的路径列表
        "-thresh", "0.5",
        "-dont_show",
        "-out", f"/tmp/result_{os.getpid()}.json"
    ]
    subprocess.run(cmd, check=True, capture_output=True)
    os.remove(tmp_list)
    return f"/tmp/result_{os.getpid()}.json"

if __name__ == "__main__":
    # 收集所有测试图
    test_imgs = sorted(glob.glob(os.path.join(TEST_IMG_DIR, "*.png")))
    # 拆分为子批次
    img_batches = list(split_list(test_imgs, BATCH_SIZE_PER_WORKER))
    # 并发执行所有批次
    with ProcessPoolExecutor(max_workers=MAX_WORKERS) as executor:
        result_files = list(executor.map(run_darknet_single_batch, img_batches))
    # 最后合并所有结果文件即可

适配Colab V100的注意事项

  • 并发数不要盲目调高:跑1张图时用!nvidia-smi查看单进程Darknet的显存占用,按单进程占用的1.5倍预留CUDA上下文开销计算最大并发数,避免Colab OOM杀进程
  • 不要用多线程启动子进程:Python GIL会限制线程并发执行,多进程才能真正调用CUDA多流资源
  • 所有文件存在Colab本地磁盘:测试图、权重、Darknet代码都放在/content目录下,不要读取挂载的Google Drive路径,避免IO瓶颈拖慢速度

内容的提问来源于stack exchange,提问作者mchd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.04 14:54:03