如何在8个字节,8个短路或8个整数的数组中找到max元素? 我可能只需要max元素的位置,max元素的值或两者的位置。
unsigned FindMax8(const uint32_t src[8]) // returns position of max element
{
unsigned ret = 0;
for (unsigned i=0; i<8; ++i)
{
if (src[i] > src[ret])
ret = i;
}
return ret;
}
在-O2
clang展开循环,但它不使用氖,这应该提供良好的性能提升(因为它消除了许多数据相关的分支?)
对于8个字节和8个短路方法应该更简单,因为整个阵列可以加载到单个q寄存器中。对于arm64来说,使用vmaxv_u16会更加简单,但是如何在32位霓虹灯中提高效率呢?
正如Marc在评论中所指出的,当函数更改为返回最大值GCC auto vectorizer generates时,对于neon64:
ldr q0, [x0, 16]
ld1r {v2.4s}, [x0]
ldr q1, [x0]
umax v0.4s, v0.4s, v2.4s
umax v0.4s, v0.4s, v1.4s
umaxv s0, v0.4s
umov w0, v0.s[0]
我有一个函数执行相当复杂的数学运算,在计算结束时我得到uint32x4_t res
结果,我需要的是得到max元素的索引。这个单件是代码中最慢的部分,到目前为止比其余数学函数的其余部分慢。
我尝试了三种不同的方法(根据探查器从最慢到最快):
使用霓虹灯进行全面计算,最后一次32位结果从霓虹灯传输到手臂。
vst1q_u32(src,res)然后使用常规C代码查找max元素的索引。
使用vget_lane_u64两次对四个32位arm寄存器进行vmov,然后使用一些位移来计算max元素的索引。
Here's fastest version that I was able to get:
unsigned compute(unsigned short *input)
{
uint32x4_t result = vld1q_u32((uint32_t*)(input));
// some computations...
// ... and at the end I end up with res01 and res23
// and I need to get index of max element from them:
uint32x2_t res01 = vget_low_u32(result);
uint32x2_t res23 = vget_high_u32(result);
// real code below:
uint64_t xres01 = vget_lane_u64(vreinterpret_u64_u32(res01), 0);
uint64_t xres23 = vget_lane_u64(vreinterpret_u64_u32(res23), 0);
unsigned ret = 0;
uint32_t xmax0 = (uint32_t)(xres01 & 0xffffffff);
uint32_t xmax1 = (uint32_t)(xres01 >> 32);
uint32_t xmax2 = (uint32_t)(xres23 & 0xffffffff);
uint32_t xmax3 = (uint32_t)(xres23 >> 32);
if (xmax1 > xmax0)
{
xmax0 = xmax1;
ret = 1;
}
if (xmax2 > xmax0)
{
xmax0 = xmax2;
ret = 2;
}
if (xmax3 > xmax0)
ret = 3;
return ret;
}
使用全霓虹计算的版本执行此操作:
{1u<<31, 1u<<30, 1u<<29, 1u<<28 }
也许在其他地方发帖,请参阅actual code我正在尝试优化。 My optimized version只需要改进最后一块。不知何故,探查器显示在我计算最大索引的最后一行中花费了80%的时间。有任何想法吗?将简单的c-loop更改为reg对可以将整个功能提高20-30%。请注意,根据分析器,两个vst1_u32是函数大部分时间都在使用的函数。
我可以尝试其他什么方法?
更新 似乎功能结束时的减速与代码无关。我不确定原因,但是当I tried to run different versions of the function取决于我打电话给他们的顺序时,我的时间会改变3-4倍。此外,通过不同的测试,如果在功能结束时没有失速,那么完整的霓虹灯版本似乎是最快的,并且我不确定为什么会发生这种失速。出于这个原因I created a new question找出原因。