【发布时间】:2015-08-13 11:34:24
【问题描述】:
我有一个对大量字节数组进行操作的算法。作为预处理步骤,我需要为给定索引创建一个计数,该计数是到目前为止在数组中设置的频率。
我可以使用以下(伪)代码在 C 中执行此操作:
input: uint8_t values[COUNT];
output: uint32_t bitsum[COUNT+1][8];
(bitsum[i][x] is the counter for the x-th bit being set in
the PRECEEDING i bytes -- this makes bitsum[0][x] == 0)
// we skip first row
for (int i=1; i < COUNT+1; i++) {
for (int bit=0; bit < 8; bit++) {
bitsum[i][bit] = bitsum[i-1][bit];
if (values[i-1] & (1 << bit) != 0) {
bitsum[i][bit]++;
}
}
}
不过,我希望使用 NEON SIMD 可以更快地实现这一目标。不幸的是,我对此很陌生,所以我还不能解决这个问题(还没有?)并寻求一些帮助。在 NEON 中甚至可以做到这一点吗?
更新:
试图在 C 中加快这段代码的速度,我相信以下方法是最快的(当然,不展开内部 for 循环):
// pre-calculate lookup-table
uint16_t lookup[256][8];
for (int value=0; value < 256; value++) {
for (int bit=0; bit < 8; bit++) {
if (value & (1 << bit) != 0) {
lookup[value][bit]++;
}
}
}
// create sum
for (int i=1; i < COUNT+1; i++) {
for (int bit=0; bit < 8; bit++) {
bitsum[i][bit] = bitsum[i-1][bit] + lookup[values[i-1]][bit];
}
}
这看起来对于 SIMD 来说是理想的,除了查找表访问 - 至少我在 NEON 中找不到这样做的方法。
【问题讨论】:
-
应该是累积的吗?您的描述听起来好像应该,但示例代码没有这样做。
-
@harold:感谢您发现这一点,它确实应该是累积的。我已经修复了伪代码(显然不是优化代码)。