NEON 增加运行时间
Posted
技术标签:
【中文标题】NEON 增加运行时间【英文标题】:NEON increasing run time 【发布时间】:2017-03-12 17:19:41 【问题描述】:我目前正在尝试优化我的一些图像处理代码以使用 NEON 指令。
假设我需要非常大的浮点数组,并且我想将第一个的每个值与第二个的三个连续值相乘。 (第二个是三倍大。)
float* l_ptrGauss_pf32 = [...];
float* l_ptrLaplace_pf32 = [...]; // Three times as large
for (uint64_t k = 0; k < l_numPixels_ui64; ++k)
float l_weight_f32 = *l_ptrGauss_pf32;
*l_ptrLaplace_pf32 *= l_weight_f32;
++l_ptrLaplace_pf32;
*l_ptrLaplace_pf32 *= l_weight_f32;
++l_ptrLaplace_pf32;
*l_ptrLaplace_pf32 *= l_weight_f32;
++l_ptrLaplace_pf32;
++l_ptrGauss_pf32;
所以当我用 NEON 内部函数替换上面的代码时,运行时间大约长了 10%。
float32x4_t l_gaussElem_f32x4;
float32x4_t l_laplElem1_f32x4;
float32x4_t l_laplElem2_f32x4;
float32x4_t l_laplElem3_f32x4;
for( uint64_t k=0; k<(l_lastPixelInBlock_ui64/4); ++k)
l_gaussElem_f32x4 = vld1q_f32(l_ptrGauss_pf32);
l_laplElem1_f32x4 = vld1q_f32(l_ptrLaplace_pf32);
l_laplElem2_f32x4 = vld1q_f32(l_ptrLaplace_pf32+4);
l_laplElem3_f32x4 = vld1q_f32(l_ptrLaplace_pf32+8);
l_laplElem1_f32x4 = vmulq_f32(l_gaussElem_f32x4, l_laplElem1_f32x4);
l_laplElem2_f32x4 = vmulq_f32(l_gaussElem_f32x4, l_laplElem2_f32x4);
l_laplElem3_f32x4 = vmulq_f32(l_gaussElem_f32x4, l_laplElem3_f32x4);
vst1q_f32(l_ptrLaplace_pf32, l_laplElem1_f32x4);
vst1q_f32(l_ptrLaplace_pf32+4, l_laplElem2_f32x4);
vst1q_f32(l_ptrLaplace_pf32+8, l_laplElem3_f32x4);
l_ptrLaplace_pf32 += 12;
l_ptrGauss_pf32 += 4;
两个版本均使用 Apple LLVM 8.0 使用 -Ofast 编译。即使没有 NEON 内在函数,编译器真的那么擅长优化这段代码吗?
【问题讨论】:
你检查编译器生成的代码了吗? Clang 确实使用了 Neon 指令(假设你“让它”),而你不必求助于内在函数,并且通常比你使用内在函数时做得更好(因为它会更聪明地安排指令和操作,其中内在函数往往被视为“必须完全这样”)。 也可能是因为你的手动展开,循环的展开或其他重新排列变得不同。 这是针对 armv7 还是 arm64 的?另外,小切线,但最好将size_t
用于k
和l_lastPixelInBlock_ui64
(因为在armv7 上是32 位)。此外,指针可以别名吗?如果没有,将它们标记为restrict
应该会有所帮助。
【参考方案1】:
您的代码包含相对较多的向量加载操作和一些乘法操作。所以我建议优化向量的加载。有两个步骤:
在阵列中使用对齐的内存。 使用预取。为了做到这一点,我建议使用下一个功能:
inline float32x4_t Load(const float * p)
// use prefetch:
__builtin_prefetch(p + 256);
// tell compiler that address is aligned:
float * _p = (float *)__builtin_assume_aligned(p, 16);
return vld1q_f32(_p);
【讨论】:
以上是关于NEON 增加运行时间的主要内容,如果未能解决你的问题,请参考以下文章
当我在 Linux 上运行使用硬浮点选项构建的 Neon 代码时出现分段错误
Eclipse Neon 上的目标运行时未列出 Tomcat 服务器
使用 neon-wallet-db + neon-js + NEO-cli /rpc 搭建轻钱包服务端