将 q 寄存器中的 128 位数据转换(求和)为 16 位数据的高效算法
Posted
技术标签:
【中文标题】将 q 寄存器中的 128 位数据转换(求和)为 16 位数据的高效算法【英文标题】:Efficient algorithm to convert(sum) 128-bit data in q-register to 16-bit data 【发布时间】:2012-08-04 10:33:20 【问题描述】:我在 q-register 中有 128 位数据。我想对这个 q 寄存器中的单个 16 位块求和,最终得到一个 16 位的最终总和(任何超过 16 位的进位都应该被添加到这个 16 位数字的 LSB 中)。
我想要实现的是:
VADD.U16(一些 16 位变量)q0[0] q0[1] q0[2] ......... q0[7]
但使用内在函数,
如果有人能给我一个算法,将不胜感激。
我尝试使用成对加法,但我最终得到了一个相当笨拙的解决方案..
下面是它的外观:
int convert128to16(uint16x8_t data128)
uint16_t data16 = 0;
uint16x4_t ddata;
print16(data128);
uint32x4_t data = vpaddlq_u16(data128);
print32(data);
uint16x4_t data_hi = vget_high_u16(data);
print16x4(data_hi);
uint16x4_t data_low = vget_low_u16(data);
print16x4(data_low);
ddata = vpadd_u16( data_hi, data_low);
print16x4(ddata);
它仍然不完整且有点笨拙。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:可以使用横向添加指令:
这是一个片段:
uint16x8_t input = /* load your data128 here */
uint64x2_t temp = vpaddlq_u32 (vpaddlq_u16 (input));
uint64x1_t result = vadd_u64 (vget_high_u64 (temp),
vget_low_u64 (temp));
// result now contains the sum of all 16 bit unsigned words
// stored in data128.
// to add the values that overflow from 16 bit just do another 16 bit
// horizontal addition and return the lowest 16 bit as the final result:
uint16x4_t w = vpadd_u16 (
vreinterpret_u16_u64 (result),
vreinterpret_u16_u64 (result));
uint16_t wrappedResult = vget_lane_u16 (w, 0);
【讨论】:
谢谢 Nils,那额外的步骤是什么?如果我必须将此结果收集到某个变量中,以便从函数返回,我将如何做到这一点?你能扩展到同一段代码吗? 非常感谢,这可以作为我许多其他任务的参考。再次感谢..【参考方案2】:如果您的目标是对 16 位块(模 16 位)求和,则可以使用以下片段:
uin16_t convert128to16(uint16x8_t data128)
data128 += (data128 >> 64);
data128 += (data128 >> 32);
data128 += (data128 >> 16);
return data128 & 0xffff;
【讨论】:
感谢您的帮助@wildplasser,但我正在寻找使用内在函数在霓虹灯上工作的代码。你的解决方案看起来很一般。如果我错了,请纠正我 是的,它是通用的。但是,如果你有一个 C 编译器,也许它足够聪明,可以找到(高度具体的)指令。但是,如果我理解正确,架构/编译器已经有一种机制将宽寄存器视为较小寄存器的“数组”。聪明的编译器会知道这一点。 同意,但我目前需要的是内在函数,我想从内在函数生成程序集并优化是一个更好的选择。比直接从 C 源代码生成/优化霓虹灯代码?这不是真的吗?以上是关于将 q 寄存器中的 128 位数据转换(求和)为 16 位数据的高效算法的主要内容,如果未能解决你的问题,请参考以下文章
NEON:如何将 128 位 ARGB 转换为具有饱和度的 32 位 ARGB?
如何将一个 XMM 128 位寄存器拆分为两个 64 位整数寄存器?
存储介于-64(十六进制)和128(十六进制)之间的值所需的最小寄存器长度?
NEON:将 uint8_t 数组加载到 128 位寄存器中