我有一个由16个整数组成的数组,我想从这个数组中找到一对彼此之间最大相似的整数。 可以使用以下(伪)代码计算差异:
int diss(uint32_t x, uint32_t y)
{ // it could do square for each byte of the number instead.
return
abs(((x >> 24) & 0xFF) - ((y >> 24) & 0xFF)) +
abs(((x >> 16) & 0xFF) - ((y >> 16) & 0xFF)) +
abs(((x >> 8) & 0xFF) - ((y >> 8) & 0xFF)) +
abs(((x >> 0) & 0xFF) - ((y >> 0) & 0xFF));
}
void findDissimilar(uint32_t buf[16], uint32_t& x, uint32_t& y)
{
int maxDiss = 0;
for (int i=0; i<16; ++i)
{
for (int j=0; j<16; ++j)
{
int d = diss(buf[i], bud[j]);
if (d > maxDiss)
{
maxDiss = d;
x = buf[i];
y = buf[j];
}
}
}
}
如果重要,在输入buf
上已经在霓虹灯寄存器中。在输出上,我应该得到两个整数(在霓虹灯中也许会更好)。
如何在手臂霓虹灯中高效地做到这一点,我应该尝试哪种方法?只是为了澄清,问题的关键在于优化findDissimilar
。
答案 0 :(得分:0)
diss
对于以霓虹灯进行计算很简单,它可以通过这种方式实现(未经测试的代码):
uint32x4_t diss_x4(uint32x4_t x4, uint32x4_t y4)
{
uint8x16_t diff = vabdq_u8(vreinterpretq_u8_u32(x4), vreinterpretq_u8_u32(x4));
uint16x8_t m0 = vmull_u8(vget_low_u8(diff), vget_low_u8(diff));
uint16x8_t m1 = vmull_u8(vget_high_u8(diff), vget_high_u8(diff));
uint16x4_t s0 = vpadd_u16(vget_low_u8(m0), vget_high_u8(m0));
uint16x4_t s1 = vpadd_u16(vget_low_u8(m1), vget_high_u8(m1));
uint16x4_t sx = vpadd_u16(s0, s1);
return vmovl_u16(sx);
}
,但对findDissimilar
而言却并非如此。我认为最好的方法是执行以下操作:
-将所有16个int装入4个q寄存器{q0, q1, q2, q3}
中。
-第一个q0 reg包含{ buf[0], buf[1], buf[2], buf[3] }
-然后我可以循环15次,并从4个输入q reg中提取出一个qext值,例如vextq_u32(q0,q1,1),以进行第一次迭代,依此类推。
-计算q0和qext之间的最小值。
然后对q1,q2,q3执行相同的过程。
也许我按字节解交{q0, q1, q2, q3}
可能会得到更好的优化。