使用NCNN benchmark测出每一层的时间

本文详细介绍了如何在腾讯NCNN框架中实现测量模型推理时间及每一层平均时间的功能。通过修改源码,添加了一个hash map记录层时间,并在forward_layer方法中计算每层耗时。在手机上运行,可以输出测试次数、线程数、powersave模式和每层的平均时间。修改包括在Net类中添加记录时间的结构,调整Extractor类的extract方法,并编写benchmark测试代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

腾讯NCNN框架中自带了测模型推理时间和每层时间的功能,然而,这些功能并没有文档写明白如何使用,也没有默认开启和计算每层的平均时间,为了更好地进行速度的测试,我重写了NCNN源码,并以此文记录下以下功能是如何实现的。

效果

在手机上,给出任何一个网络可以用的ncnn param文件,可以得到以下的结果:

loop_count = 10
num_threads = 4
powersave = 2
output_blob_name: prob
mode: cls

resnet18.param :

Convolution conv1 8.014ms | feature_map: 224 x 224 inch: 3 outch: 64 kernel: 7 x 7 stride: 2
BatchNorm bn_conv1 0.336ms | feature_map: 112 x 112 inch: 64 outch: 64
Scale scale_conv1 0.218ms | feature_map: 112 x 112 inch: 64 outch: 64
ReLU conv1_relu 0.200ms | feature_map: 112 x 112 inch: 64 outch: 64
Pooling pool1 0.534ms | feature_map: 112 x 112 inch: 64 outch: 64 kernel: 3 x 3 stride: 2
Split splitncnn_0 0.001ms |
Convolution res2a_branch1 0.854ms | feature_map: 56 x 56 inch: 64 outch: 64 kernel: 1 x 1
BatchNorm bn2a_branch1 0.052ms | feature_map: 56 x 56 inch: 64 outch: 64
Scale scale2a_branch1 0.028ms | feature_map: 56 x 56 inch: 64 outch: 64
Convolution res2a_branch2a 3.417ms | feature_map: 56 x 56 inch: 64 outch: 64 kernel: 3 x 3
BatchNorm bn2a_branch2a 0.120ms | feature_map: 56 x 56 inch: 64 outch: 64
Scale scale2a_branch2a 0.078ms | feature_map: 56 x 56 inch: 64 outch: 64
ReLU res2a_branch2a_relu 0.047ms | feature_map: 56 x 56 inch: 64 outch: 64
Convolution res2a_branch2b 3.274ms | feature_map: 56 x 56 inch: 64 outch: 64 kernel: 3 x 3
BatchNorm bn2a_branch2b 0.113ms | feature_map: 56 x 56 inch: 64 outch: 64
Scale scale2a_branch2b 0.139ms | feature_map: 56 x 56 inch: 64 outch: 64
Eltwise res2a 0.146ms |
ReLU res2a_relu 0.095ms | feature_map: 56 x 56 inch: 64 outch: 64
Split splitncnn_1 0.001ms |
Convolution res2b_branch2a 3.356ms | feature_map: 56 x 56 inch: 64 outch: 64 kernel: 3 x 3
BatchNorm bn2b_branch2a 0.107ms | feature_map: 56 x 56 inch: 64 outch: 64
Scale scale2b_branch2a 0.085ms | feature_map: 56 x 56 inch: 64 outch: 64
ReLU res2b_branch2a_relu 0.106ms | feature_map: 56 x 56 inch: 64 outch: 64
Convolution res2b_branch2b 3.544ms | feature_map: 56 x 56 inch: 64 outch: 64 kernel: 3 x 3
BatchNorm bn2b_branch2b 0.065ms | feature_map: 56 x 56 inch: 64 outch: 64
Scale scale2b_branch2b 0.128ms | feature_map: 56 x 56 inch: 64 outch: 64
Eltwise res2b 0.159ms |
ReLU res2b_relu 0.110ms | feature_map: 56 x 56 inch: 64 outch: 64
Split splitncnn_2 0.001ms |
Convolution res3a_branch1 0.679ms | feature_map: 56 x 56 inch: 64 outch: 128 kernel: 1 x 1 stride: 2
BatchNorm bn3a_branch1 0.044ms | feature_map: 28 x 28 inch: 128 outch: 128
Scale scale3a_branch1 0.119ms | feature_map: 28 x 28 inch: 128 outch: 128
Convolution res3a_branch2a 2.173ms | feature_map: 56 x 56 inch: 64 outch: 128 kernel: 3 x 3 stride: 2
BatchNorm bn3a_branch2a 0.071ms | feature_map: 28 x 28 inch: 128 outch: 128
Scale scale3a_branch2a 0.035ms | feature_map: 28 x 28 inch: 128 outch: 128
ReLU res3a_branch2a_relu 0.115ms | feature_map: 28 x 28 inch: 128 outch: 128
Convolution res3a_branch2b 2.586ms | feature_map: 28 x 28 inch: 128 outch: 128 kernel: 3 x 3
BatchNorm bn3a_branch2b 0.102ms | feature_map: 28 x 28 inch: 128 outch: 128
Scale scale3a_branch2b 0.045ms | feature_map: 28 x 28 inch: 
<think>好的,我现在需要解决用户提出的关于YOLO模型在安卓设备上部署时精度下降的问题。首先,我要理解用户的问题背景。用户可能已经在训练阶段得到了不错的模型精度,但在安卓设备上实际运行时发现精度下降,这可能影响目标检测的效果,比如在番茄病害检测的应用中无法准确识别病害,进而影响后续的补救建议。 接下来,我需要分析可能的原因。根据已有的知识和经验,可能的原因包括模型量化带来的精度损失、硬件性能限制、预处理和后处理的差异、框架兼容性问题,以及训练和部署环境的不一致等。同时,参考用户提供的引用资料,比如引用[1]提到ncnn支持模型量化,可能会影响精度;引用[4]中提到的YOLOv5在移动端的应用,可能涉及数据增强和模型优化技巧,这些都需要考虑。 然后,我需要逐一分析每个可能的原因,并给出相应的解决方案。例如,模型量化虽然减少了计算量和内存占用,但可能降低精度,因此可以尝试调整量化参数或使用混合量化。硬件性能方面,安卓设备的算力有限,可能需要简化模型结构或使用更轻量级的版本。预处理和后处理的差异可能导致输入数据不一致,需要确保部署时的处理与训练时一致。框架兼容性方面,不同推理引擎可能有不同的实现,检查层支持情况或更换引擎可能有帮助。此外,训练数据与真实场景的差异,可能需要增加数据增强或进行域适应训练。 还需要考虑用户的具体应用场景,比如番茄病害检测,可能在移动端部署时,输入图像的分辨率或光照条件与训练数据不同,导致模型表现下降。这时候可能需要针对移动端的环境进行数据增强,或者在应用中加入自动调整图像质量的模块。 然后,我需要将分析的原因和解决方案结构化,确保逻辑清晰,步骤明确。同时,按照用户的要求,生成相关问题,帮助用户进一步探索解决方案。最后,确保回答符合格式要求,如使用中文、正确引用文献、分点列出等,并且避免使用Markdown格式,保持自然的口语化表达。</think>### YOLO模型安卓部署精度下降的原因及解决方案 #### 一、精度下降的常见原因 1. **模型量化损失** 安卓端部署常使用量化技术(如ncnn支持的8位量化),降低模型精度以提升速度,但可能导致数值范围压缩和激活函数误差积累[^1]。例如,浮点型权重转换为整型时,$w_{int} = \text{round}(w_{float}/scale)$ 会引入舍入误差。 2. **硬件性能限制** 移动端GPU/CPU算力不足,导致模型推理时跳过部分计算(如非极大值抑制阈值自动调整),影响检测置信度。例如,ARM Mali GPU的FP16计算可能因精度不足导致边界框坐标偏移。 3. **预处理/后处理不一致** 训练时使用OpenCV的BGR格式和双线性插值,而安卓端可能因图像库差异(如Bitmap默认RGB格式)导致输入数据分布偏移,计算误差可达$\Delta= |RGB_{mean} - BGR_{mean}| \geq 15$。 4. **框架兼容性问题** TensorFlow Lite或NCNN对某些算子支持不完善(如自定义SPP层),可能自动替换为近似实现。例如,YOLO的Focus层在部分框架中需拆解为切片+卷积操作,可能损失特征图信息[^3]。 #### 二、解决方案及实施步骤 1. **量化校准优化** - 使用动态范围量化代替全整型量化 ```python converter = tf.lite.TFLiteConverter.from_keras_model(model) converter.optimizations = [tf.lite.Optimize.DEFAULT] # 动态量化 tflite_model = converter.convert() ``` - 对敏感层(如检测头)保留FP16精度,参考ncnn的混合精度量化策略 2. **输入数据对齐** 在安卓端严格复现训练预处理流程: ```kotlin val inputTensor = TensorImage(DataType.FLOAT32) inputTensor.load(bitmap) inputTensor = imageProcessor.process(inputTensor) // 必须包含BGR转换、/255归一化等操作 ``` 3. **模型结构适配** - 将YOLOv5的Focus层替换为Conv+BN组合(v6.0后官方推荐) - 使用深度可分离卷积重构检测头,例如将$3\times3$ Conv替换为$DWConv+1\times1 Conv$,参数量减少约$70\%$ 4. **后处理强化** 在Java层实现精确的非极大值抑制: ```java MatrixNMS.builder() .setMinScoreThreshold(0.5f) .setMinSuppressionThreshold(0.6f) .setMaxOutputSize(20) // 与训练时保持一致 .build(); ``` 5. **设备感知训练** 在模型训练阶段引入移动端噪声: ```python class MobileAwareAugmentation: def __call__(self, image): image = add_jpeg_compression(image, quality=random.randint(65,85)) # 模拟移动端传输压缩 image = add_gaussian_blur(image, radius=random.randint(1,2)) # 模拟摄像头噪声 return image ``` #### 三、验证方法 1. 部署后精度评估流程: $$ \text{精度差异} = \frac{1}{N}\sum_{i=1}^N \left| \frac{AP_{\text{server}} - AP_{\text{mobile}}}{AP_{\text{server}}} \right| \times 100\% $$ 建议差异控制在5%以内 2. 使用TensorFlow Lite的基准测试工具分析层级误差: ```bash benchmark_model --graph=yolo.tflite --enable_op_profiling=true ``` #### 四、典型修复案例 在番茄病害检测项目中[^4],通过以下改进将mAP从0.68提升至0.74: 1. 将输入分辨率从640×640调整为384×384,降低计算需求 2. 对病害特征明显的浅层网络(如P2层)禁用量化 3. 添加移动端专用的Mosaic数据增强(包含30%的手机拍摄模拟数据)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值