arm - ARM NEON:常规 C 代码在简单乘法中比 ARM Neon 代码更快?
问题描述
我正在使用 ARM NEON 内在函数为数组实现简单的乘法。输入是一个 uint8 数组,输出是一个 uint16 数组。但是,常规的本机代码比 NEON 优化的代码要快。谁能帮我弄清楚如何改进 NEON 代码?
我的常规代码是
uint16_t scale_factor = 300;
for(int i = 0; i < output_size; i++)
{
out_16bit[i] = (uint16_t)(in_ptr[i] * scale_factor) ;
}
我的霓虹灯代码是
uint16_t* out_ptr = out_16bit;
uint8_t* in_ptr = in_8bit;
uint16_t scale_factor = 300;
for(int i = 0; i < out_size/16; i++)
{
uint8x16_t in_v0 = vld1q_u8(in_ptr);
in_ptr += 16;
uint16x8_t in_16_v0 = vmovl_u8(vget_low_u8(in_v0));
uint16x8_t in_16_v1 = vmovl_u8(vget_high_u8(in_v0));
uint16x8_t res_0 = vmulq_n_u16(in_16_v0, scale_factor);
uint16x8_t res_1 = vmulq_n_u16(in_16_v1, scale_factor);
// code below takes long time
vst1q_u16(out_ptr,res_0);
vst1q_u16(out_ptr+8,res_1);
out_ptr += 16;
}
我还做了一些分析,发现如果我注释掉vst1q_u16
s 或out_ptr += 16
,速度很快。但如果我保持上述两个,它会很慢。所以我想这可能是因为指针的增量正在等待完成vst1q_u16
?然后我更新了NEON代码以在和之间添加一些代码vst1q_u16
,out_ptr+=16
如下所示,
uint8x16_t in_v0 = vld1q_u8(in_ptr);
uint16x8_t in_16_v0 = vmovl_u8(vget_low_u8(in_v0));
uint16x8_t in_16_v1 = vmovl_u8(vget_high_u8(in_v0));
uint16x8_t res_0 = vmulq_n_u16(in_16_v0, scale_factor);
uint16x8_t res_1 = vmulq_n_u16(in_16_v1, scale_factor);
vst1q_u16(out_ptr,res_0);
vst1q_u16(out_ptr+8,res_1);
for(int i = 1; i < out_size/16; i++)
{
in_v0 = vld1q_u8(in_ptr);
in_16_v0 = vmovl_u8(vget_low_u8(in_v0));
in_16_v1 = vmovl_u8(vget_high_u8(in_v0));
out_ptr += 16;
res_0 = vmulq_n_u16(in_16_v0, scale_factor);
res_1 = vmulq_n_u16(in_16_v1, scale_factor);
vst1q_u16(out_ptr,res_0);
vst1q_u16(out_ptr+8,res_1);
}
但是这个改变没有奏效......请帮助告诉我应该怎么做......谢谢。
解决方案
如评论中所述,简单的答案是自动矢量化。我不确定clang 6,但在以Neon平台为目标时,最近的clang肯定会默认自动矢量化为Neon,并且很难在像这种乘法这样简单的事情上击败自动矢量化。也许为您的特定处理器展开最佳循环。但它很容易比自动矢量化更糟糕。Godbolt 是一个非常好的比较方法,以及分析您的所有更改。
所有的评论也都很好。
有关 Neon 内在函数最佳实践的更多文档,Arm 的Neon 微型网站有非常有用的信息,尤其是关于Optimizing C with Neon intrinsics的文档。
推荐阅读
- android - Android Navigation Safe Args 传递 LiveData 和 Lambda 变量
- ios - iOS - 控制“${App} 想要打开 ${Another App}”对话框
- c# - 使用脚本将对象 [SerializeField] 更改为另一个
- python - 如何在 Windows 启动时启动 python 文件?
- python-3.x - Python - 在 pyinstaller exe 中使用 librosa.load() 时找不到 registry.txt
- python - 设计游戏建议
- javascript - 打字稿条件继承
- c++ - 是否可以在 cmake 中编写一个忽略以某种方式结尾的文件的 GLOB_RECURSE ?
- android - 如何解决 Dagger (Hilt) 中的循环依赖关系
- python - cv2.videoCapture 仅返回“uri 中缺少端口”