Detectron2 训练速度基准测试全解读:Mask R-CNN 跨框架吞吐量对比、测试方法与复现指南
【免费下载链接】detectron2Detectron2 is a platform for object detection, segmentation and other visual recognition tasks.项目地址: https://gitcode.com/GitHub_Trending/de/detectron2
导读:本文以 Detectron2 官方基准测试文档为核心,系统讲解其 Mask R-CNN(R-50-FPN)训练吞吐量测试的完整方案——包括软硬件环境、测试指标定义、主流开源实现的速度对比结果,以及每个框架的精确复现命令与超参对齐细节。读完本文,你将掌握"如何设计公平的 R-CNN 训练速度基准"的方法论,并能在当前仓库中直接复现 Detectron2 一侧的测量,同时理解为何 R-CNN 类模型的训练吞吐量会随训练过程动态变化。
一、为什么要为 Mask R-CNN 做跨框架训练速度基准
训练速度(Training Throughput)是评估一个目标检测/实例分割框架实用价值的关键指标之一。相比推理延迟(inference latency),训练吞吐量更能反映一个框架在真实研究迭代中的产出效率——同样的时间能完成多少轮实验、多少张图片的处理。
Detectron2 官方在 docs/notes/benchmarks.md 中发布了一份专门的基准测试,其目的非常聚焦:在尽量统一的模型与超参数前提下,横向对比 Detectron2 与其他主流开源 Mask R-CNN 实现的训练速度,从而给使用者提供选型参考。参与对比的实现包括:
- Detectron2(PyTorch 框架)
- mmdetection(PyTorch 框架,OpenMMLab 出品)
- maskrcnn-benchmark(PyTorch 框架,Facebook 早期作品)
- tensorpack(TensorFlow 框架)
- SimpleDet(MXNet 框架)
- Detectron(Caffe2 框架,Detectron2 的前身)
- matterport/Mask_RCNN(TensorFlow/Keras 框架)
这是一个极具代表性的对比阵容:几乎覆盖了 2020 年前后社区中最主流的 Mask R-CNN 开源实现,且框架横跨 PyTorch、TensorFlow、MXNet、Caffe2。
值得注意的是,该基准测试文档本身不包含任何图片素材(表格以 reStructuredText 的eval_rst指令内嵌,徽标为外部图片引用),因此本文也不引入与本主题无关的配图,一切结论以数据表格和源码为据。
二、测试设置:软硬件环境与指标定义
2.1 硬件与软件环境
为了让各框架之间的比较尽量公平,基准测试固定了统一的运行环境:
| 项目 | 配置 |
|---|---|
| 硬件 | 8 张 NVIDIA V100 GPU(NVLink 互联) |
| Python | 3.7 |
| CUDA | 10.1 |
| cuDNN | 7.6.5 |
| PyTorch | 1.5 |
| TensorFlow | 1.15.0rc2 |
| Keras | 2.2.5 |
| MXNet | 1.6.0b20190820 |
需要强调两点:
- 不同框架无法运行在同一套深度学习运行时之上。因此这份基准选择了"同一硬件、各自框架的当时主流版本"的组合,属于"软硬件尽量对齐"的近似公平,而非严格同环境的 micro-benchmark。
- 表格中的吞吐量数字绑定这些特定的版本组合。由于软件版本(尤其是各框架自身的算子优化与数据流水线实现)会显著影响吞吐量,本文作者在文档中也明确承认"我们观察到的 maskrcnn-benchmark 速度比它的 model zoo 记录更快,很可能是软件版本不同的缘故"。因此,这些数字适合作为同一环境下的横向参考,不宜直接迁移到其他硬件或版本组合。
2.2 被测模型:与 Detectron 基线对齐的 R-50-FPN Mask R-CNN
被测模型为端到端(end-to-end)R-50-FPN Mask R-CNN,超参数与 Detectron 基线配置(e2e_mask_rcnn_R-50-FPN_1x.yaml) 保持一致,其关键特征是没有尺度增强(no scale augmentation)。
这一点在当前仓库中可以直接验证:基准测试使用的正是仓库内的 configs/Detectron1-Comparisons/mask_rcnn_R_50_FPN_noaug_1x.yaml,该配置继承自 configs/Base-RCNN-FPN.yaml,并显式做了以下对齐修改:
_BASE_: "../Base-RCNN-FPN.yaml" MODEL: WEIGHTS: "detectron2://ImageNetPretrained/MSRA/R-50.pkl" MASK_ON: True RESNETS: DEPTH: 50 # Detectron1 uses smooth L1 loss with some magic beta values. # The defaults are changed to L1 loss in Detectron2. RPN: SMOOTH_L1_BETA: 0.1111 ROI_BOX_HEAD: SMOOTH_L1_BETA: 1.0 POOLER_SAMPLING_RATIO: 2 POOLER_TYPE: "ROIAlign" ROI_MASK_HEAD: POOLER_SAMPLING_RATIO: 2 POOLER_TYPE: "ROIAlign" INPUT: # no scale augmentation MIN_SIZE_TRAIN: (800, )对比基线与 Detectron2 默认行为,可以提炼出几处关键差异(这在 configs/Detectron1-Comparisons/README.md 中有系统说明):
| 维度 | Detectron2 默认 | Detectron1-Comparisons(本基准所用) |
|---|---|---|
| 训练尺度增强 | 多尺度采样MIN_SIZE_TRAIN: (640, 672, 704, 736, 768, 800) | 固定短边MIN_SIZE_TRAIN: (800, ),无尺度增强 |
| 边框回归损失 | L1 loss | smooth L1 loss(SMOOTH_L1_BETA使用 Detectron1 的取值) |
| ROIAlign | ROIAlignV2(默认半像素对齐) | ROIAlign(旧行为),POOLER_SAMPLING_RATIO: 2 |
之所以这样对齐,是因为这些默认差异会同时影响精度和速度:例如尺度增强会改变输入图尺寸分布,进而影响每轮迭代的平均计算量。该目录的定位就是"尽可能贴近 Detectron 的行为,从而给出与 Detectron 之间公平的精度与速度对比"(见 configs/Detectron1-Comparisons/README.md)。
2.3 指标定义:为什么取第 100–500 轮迭代的平均值
这是整个基准测试最容易被忽略、也最重要的方法论细节:
Metrics: We use the average throughput in iterations 100-500 to skip GPU warmup time.
即:吞吐量 = 第 100 到 500 轮迭代之间的平均吞吐(images/second),目的是跳过 GPU 预热(warmup)阶段——前若干轮迭代通常伴随算子库 autotune、CUDA 上下文初始化、数据缓存填充等开销,会拉低平均速度。
文档同时给出了一个深刻的警示:
R-CNN 类模型的吞吐量在训练过程中通常会变化,因为它依赖模型自身的预测结果(proposal 数量、ROI 分布等会随训练进行而变化)。
因此:
- 该指标不能直接与 Model Zoo 中的 "train speed" 比较——Model Zoo 记录的是整个训练过程的平均速度(如 MODEL_ZOO.md 表格中的
train time (s/iter)列,例如 Faster R-CNN R50-FPN 1x 为 0.219 s/iter,这些是整轮训练的平均值); - 它更适合用于框架间同口径对比,即大家用完全相同的测量窗口(100–500 迭代)来比。
这一设计说明作者深谙 R-CNN 流水线的特性:它的计算图前向路径长度不是静态的,而是由每张图的 RPN proposal 数量动态决定。
三、主结果:7 个实现的吞吐量对比
原文档以eval_rst表格给出结果,这里整理为普通 Markdown 表格(实现后括号内为底层深度学习框架):
| 实现 | 框架 | 吞吐量(img/s) |
|---|---|---|
| Detectron2 | PyTorch | 62 |
| mmdetection | PyTorch | 53 |
| maskrcnn-benchmark | PyTorch | 53 |
| tensorpack | TensorFlow | 50 |
| SimpleDet | MXNet | 39 |
| Detectron | Caffe2 | 19 |
| matterport/Mask_RCNN | TensorFlow | 14 |
几点值得展开的观察:
- 同框架内部差距源于工程实现:三个 PyTorch 实现(62 vs 53 vs 53)跑出了明显不同的速度,说明在相同底层框架下,数据流水线、算子融合、分布式训练实现等工程细节对吞吐量的影响甚至超过框架本身的差异。
- Detectron 的 19 img/s 明显偏低,文档给出的解释是"其大量算子运行在 CPU 上,因此性能受限"。
- matterport/Mask_RCNN 的 14 img/s 最低,文档同时提醒"该实现中有许多小细节可能与 Detectron 的标准不一致",因此这个数字更多代表"该实现默认代码的速度",而非理论最优。
需要注意的边界:这些数字是该特定软硬件组合下的实测值,本文不将其外推为"永恒的速度排名",也不据此断言哪个框架"最好"——任何训练速度排名都会随硬件代际、软件版本与优化投入而改变。
四、各实现的复现命令与对齐细节
原文档为每个实现都提供了精确到 commit 的复现步骤,这是这份基准最大的工程价值。下面逐项展开。
4.1 Detectron2(本仓库):release v0.1.2
python tools/train_net.py --config-file configs/Detectron1-Comparisons/mask_rcnn_R_50_FPN_noaug_1x.yaml --num-gpus 8对应命令的入口是 tools/train_net.py:它解析命令行参数后,通过launch(main, args.num_gpus, ...)启动多进程分布式训练;launch的实现位于 detectron2/engine/launch.py,当world_size = num_machines * num_gpus_per_machine > 1时,会为每张 GPU 派生一个子进程,用 NCCL 作为后端初始化torch.distributed进程组,并自动选择空闲端口(dist_url="auto"时通过_find_free_port()动态获取)。这正是--num-gpus 8能在一台 8 卡机器上无缝工作的底层机制。
需要说明:
- 命令中的
--config-file指向的正是上文展开的 noaug 配置; - 训练脚本同时支持
--eval-only、--resume、--num-machines、--machine-rank等标准参数(见default_argument_parser),可供复现时灵活调整; - 若想仅测量数据加载或前向速度而不跑完整训练,仓库还提供了独立的 tools/benchmark.py(依赖
psutil),它支持对 yaml 配置(get_cfg路径)与 lazy 配置(LazyConfig路径)分别构建 DataLoader 基准与模型基准,可作为官方基准测试方法的本地延伸。
4.2 mmdetection:commit b0d845f
./tools/dist_train.sh configs/mask_rcnn/mask_rcnn_r50_caffe_fpn_1x_coco.py 8dist_train.sh是 mmdetection 自带的多卡训练启动脚本,第二个参数 8 表示使用 8 张 GPU。配置mask_rcnn_r50_caffe_fpn_1x_coco.py对应与 Detectron 基线同口径的 R-50-FPN Mask R-CNN 模型(caffe 风格预训练权重)。
4.3 maskrcnn-benchmark:commit 0ce8f6f
该仓库较老,需要先做 PyTorch 1.5 兼容性修补:
sed -i 's/torch.uint8/torch.bool/g' **/*.py; sed -i 's/AT_CHECK/TORCH_CHECK/g' **/*.cu然后以torch.distributed.launch启动:
python -m torch.distributed.launch --nproc_per_node=8 tools/train_net.py --config-file configs/e2e_mask_rcnn_R_50_FPN_1x.yaml文档特别注明:其观测到的速度比 maskrcnn-benchmark 自己的 model zoo 记录更快,很可能是因为软件版本不同。这再次印证了上一节的观点——版本差异足以改变速度排名,复现时必须锁定 commit。
4.4 tensorpack:commit caafda
export TF_CUDNN_USE_AUTOTUNE=0 mpirun -np 8 ./train.py --config DATA.BASEDIR=/data/coco TRAINER=horovod BACKBONE.STRIDE_1X1=True TRAIN.STEPS_PER_EPOCH=50 --load ImageNet-R50-AlignPadding.npz要点:
- 设置
TF_CUDNN_USE_AUTOTUNE=0关闭 cuDNN autotune,避免预热阶段的 autotune 干扰测量(这与官方"跳过 100–500 迭代预热"的思路一脉相承); - 使用 Horovod 分布式训练器,
-np 8指定 8 个进程; TRAIN.STEPS_PER_EPOCH=50等参数用于对齐训练 schedule。
4.5 SimpleDet:commit 9187a1
python detection_train.py --config config/mask_r50v1_fpn_1x.pySimpleDet 是基于 MXNet 的实现,其默认配置即为 8 卡训练。
4.6 Detectron(Caffe2):官方基线配置
python tools/train_net.py --cfg configs/12_2017_baselines/e2e_mask_rcnn_R-50-FPN_1x.yaml注意 Detectron 使用--cfg而不是--config-file。文档明确指出其性能受限的原因:"许多算子运行在 CPU 上"——这是它只跑出 19 img/s 的直接解释,也恰好衬托出 Detectron2 全算子 GPU 化的工程收益。
4.7 matterport/Mask_RCNN:commit 3deaec + 超参补丁
该实现默认超参与 Detectron 基线差异较大,官方提供了一段 diff 来对齐(摘要如下,完整 diff 见原文档):
diff --git i/mrcnn/model.py w/mrcnn/model.py - validation_data=val_generator, - validation_steps=self.config.VALIDATION_STEPS, + #validation_data=val_generator, + #validation_steps=self.config.VALIDATION_STEPS, diff --git i/mrcnn/parallel_model.py w/mrcnn/parallel_model.py class ParallelModel(KM.Model): ... + super().__init__() diff --git i/samples/coco/coco.py w/samples/coco/coco.py - # GPU_COUNT = 8 + GPU_COUNT = 8 + BACKBONE = "resnet50" + STEPS_PER_EPOCH = 50 + TRAIN_ROIS_PER_IMAGE = 512 ... - # Training - Stage 1 - print("Training network heads") model.train(dataset_train, dataset_val, learning_rate=config.LEARNING_RATE, epochs=40, - layers='heads', - augmentation=augmentation) - - # Training - Stage 2 - # Finetune layers from ResNet stage 4 and up - print("Fine tune Resnet stage 4 and up") - model.train(dataset_train, dataset_val, - learning_rate=config.LEARNING_RATE, - epochs=120, - layers='4+', - augmentation=augmentation) - - # Training - Stage 3 - # Fine tune all layers - print("Fine tune all layers") - model.train(dataset_train, dataset_val, - learning_rate=config.LEARNING_RATE / 10, - epochs=160, - layers='all', + layers='3+', augmentation=augmentation)补丁要点解读:
- 关闭验证回调(
model.py):原实现每个 epoch 都会跑验证集,会严重稀释训练吞吐量的测量,因此注释掉validation_data/validation_steps; - 修复 Keras 多进程模型的初始化(
parallel_model.py):ParallelModel缺少super().__init__(),在目标 Keras 版本下会报错; - 对齐超参数(
coco.py):开启GPU_COUNT = 8、固定BACKBONE = "resnet50"、STEPS_PER_EPOCH = 50、TRAIN_ROIS_PER_IMAGE = 512,并把三阶段训练(heads → 4+ → all)合并为单阶段layers='3+'、40 epochs,使训练流程与 Detectron 基线的单阶段 1x schedule 对齐。
应用补丁、export TF_CUDNN_USE_AUTOTUNE=0之后,运行:
python coco.py train --dataset=/data/coco/ --model=imagenet五、如何理解与复现这份基准:方法论要点
把整份基准拆解为方法论,可以提炼出四个可复用的设计原则:
- 统一硬件、锁定软件版本:8×V100 + 各框架当时主流版本;对老仓库精确到 commit(mmdetection
b0d845f、maskrcnn-benchmark0ce8f6f、tensorpackcaafda、SimpleDet9187a1、matterport3deaec)。 - 统一模型与超参口径:全部采用"无尺度增强的 R-50-FPN Mask R-CNN",并以 Detectron 官方基线配置为锚点逐项对齐(损失函数、ROIAlign 行为、采样比例、每图 ROI 数等)。仓库内 configs/Detectron1-Comparisons/ 目录下的三个 noaug/1x 配置(Faster R-CNN、Keypoint R-CNN、Mask R-CNN)就是这套"对齐思想"的落地产物。
- 统一测量口径:取第 100–500 轮迭代的平均吞吐以跳过预热;关闭 cuDNN autotune(TF 侧);并明确区分"窗口平均吞吐"与"整轮训练平均速度"(后者即 MODEL_ZOO.md 的
train time (s/iter)列,两者不可直接比较)。 - 透明披露差异:文档不掩盖各实现之间的额外差异(如 maskrcnn-benchmark 因版本更快、matterport 的细节差异、Detectron 的 CPU 算子瓶颈),并逐一给出原因说明。
若要在当前仓库复现 Detectron2 一侧,建议:
# 1. 按 INSTALL.md 安装依赖(Python 3.7+ / PyTorch / CUDA) # 2. 准备 COCO 数据集并按要求注册 python tools/train_net.py \ --config-file configs/Detectron1-Comparisons/mask_rcnn_R_50_FPN_noaug_1x.yaml \ --num-gpus 8运行时会通过 tools/train_net.py 的setup()加载并冻结配置,日志中可通过CommonMetricPrinter观察每轮迭代耗时,据此按"第 100–500 轮平均"的口径自行统计吞吐量。
六、延伸阅读
- 基准结论与 Detectron 的精度对比补充:configs/Detectron1-Comparisons/README.md(其中给出了 Faster/Keypoint/Mask R-CNN 与 Detectron 的 AP 对照,以及"Detectron2 的 mask AP 高出约 1 个点、源于更正确的实现"的说明)
- Detectron2 与旧库(Detectron、Caffe2、TensorFlow)的兼容性与行为差异:docs/notes/compatibility.md(覆盖 box 尺寸约定、anchor 量化、类别标签顺序、ROIAlign 半像素对齐、mask 推理函数等)
- 各模型的整轮训练速度、推理速度与显存占用(
train time (s/iter)口径):MODEL_ZOO.md - 训练入口脚本与分布式启动机制:tools/train_net.py、detectron2/engine/launch.py
- 独立的基准测试工具(DataLoader 与模型两路):tools/benchmark.py
【免费下载链接】detectron2Detectron2 is a platform for object detection, segmentation and other visual recognition tasks.项目地址: https://gitcode.com/GitHub_Trending/de/detectron2
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考