maskrcnn_benchmark 仓库中最大的瓶颈是什么?

我正在使用maskrcnn_benchmark 仓库进行一个项目。我已经详细探索了这个基准测试仓库,试图找出它在 CPU 上性能较慢的原因,相较于此处链接描述来说。

为了对各个前向传递进行基准测试,我为每个部分设置了一个时间计数器,这样我就可以知道计算每个组件所需的时间。我很难准确找出整个架构中最慢的组件。我认为它可能是maskrcnn_benchmark/modeling/backbone/resnet.py文件中的BottleneckWithFixedBatchNorm类。

我非常希望能得到关于定位这个架构中最大瓶颈的帮助。


回答:

我遇到了同样的问题,最好的解决方案是深入查看主代码,逐个模块地检查前向传递,并设置计时器来记录每个模块计算所花费的时间。我们的工作方法是创建一个架构,为每个类设置时间记录器,因此每个类的实例都会记录其执行时间。经过详细比较,至少在我们的案例中,我们发现延迟的原因是Resnet模块的深度,(考虑到Resnet的计算成本,这并不令人惊讶,唯一的解决方案是更多的并行化处理,因此要么确保使用更大的GPU来执行任务,要么减少Resnet网络的深度)。

我必须告知,maskrcnn_benchmark 已经废弃,现在有一个更新版本,即detectron2。考虑迁移您的代码,以在架构上获得显著的速度提升。

BottleneckWithFixedBatchNorm并不是架构中最昂贵的操作,当然也不是造成瓶颈的原因,尽管它的名字可能让人误解。这个类在计算上并不昂贵,并且即使在低端CPU机器上也能并行计算(至少在推理阶段)。

可以从路径maskrcnn_benchmark/modeling/backbone/resnet.py中找到一个更好的跟踪每个模块性能的代码示例

class ResNet(nn.Module):    def __init__(self, cfg):        super(ResNet, self).__init__()        # 如果我们想在forward()中使用cfg,那么我们应该制作一个副本并存储以备后用:        # self.cfg = cfg.clone()        # 将字符串名称转换为实现        stem_module = _STEM_MODULES[cfg.MODEL.RESNETS.STEM_FUNC]        stage_specs = _STAGE_SPECS[cfg.MODEL.BACKBONE.CONV_BODY]        transformation_module = _TRANSFORMATION_MODULES[cfg.MODEL.RESNETS.TRANS_FUNC]        # 构建stem模块        self.stem = stem_module(cfg)        # 构建指定的ResNet阶段        num_groups = cfg.MODEL.RESNETS.NUM_GROUPS        width_per_group = cfg.MODEL.RESNETS.WIDTH_PER_GROUP        in_channels = cfg.MODEL.RESNETS.STEM_OUT_CHANNELS        stage2_bottleneck_channels = num_groups * width_per_group        stage2_out_channels = cfg.MODEL.RESNETS.RES2_OUT_CHANNELS        self.stages = []        self.return_features = {}        for stage_spec in stage_specs:            name = "layer" + str(stage_spec.index)            stage2_relative_factor = 2 ** (stage_spec.index - 1)            bottleneck_channels = stage2_bottleneck_channels * stage2_relative_factor            out_channels = stage2_out_channels * stage2_relative_factor            stage_with_dcn = cfg.MODEL.RESNETS.STAGE_WITH_DCN[stage_spec.index -1]            module = _make_stage(                transformation_module,                in_channels,                bottleneck_channels,                out_channels,                stage_spec.block_count,                num_groups,                cfg.MODEL.RESNETS.STRIDE_IN_1X1,                first_stride=int(stage_spec.index > 1) + 1,                dcn_config={                    "stage_with_dcn": stage_with_dcn,                    "with_modulated_dcn": cfg.MODEL.RESNETS.WITH_MODULATED_DCN,                    "deformable_groups": cfg.MODEL.RESNETS.DEFORMABLE_GROUPS,                }            )            in_channels = out_channels            self.add_module(name, module)            self.stages.append(name)            self.return_features[name] = stage_spec.return_features        # 可选地冻结(requires_grad=False)骨干网络的部分        self._freeze_backbone(cfg.MODEL.BACKBONE.FREEZE_CONV_BODY_AT)    def _freeze_backbone(self, freeze_at):        if freeze_at < 0:            return        for stage_index in range(freeze_at):            if stage_index == 0:                m = self.stem  # 阶段0是stem            else:                m = getattr(self, "layer" + str(stage_index))            for p in m.parameters():                p.requires_grad = False    def forward(self, x):        start_timer=time.time()        outputs = []        x = self.stem(x)        for stage_name in self.stages:            x = getattr(self, stage_name)(x)            if self.return_features[stage_name]:                outputs.append(x)        print("ResNet time :: ", time.time()-start_timer,file=open("timelogger.log","a"))        return outputs

唯一需要做的更改是在前向传递中,所有由此类创建的实例将继承属性并记录时间(选择将记录写入文件而不是简单地输出到标准输出)。

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注