如何高效计算uint8_t缓冲区按位和?是否有BLAS/Boost相关接口?
问题解答
现成库调用说明
目前BLAS和Boost库均没有直接匹配该需求的现成例程:
- BLAS的设计目标是线性代数领域的矩阵、向量运算,核心支持浮点及大位宽整数的乘加运算,这类按比特维度的跨缓冲区归约操作不属于BLAS的常规算子覆盖范围
- Boost也没有公开的通用API专门实现该特定的按位计数需求
高效实现方案
该操作确实属于高度可向量化的运算,下面给出两种比朴素实现性能提升明显的方案:
方案1:查表优化(通用平台兼容,无指令集依赖)
利用uint8_t只有256种取值的特性,提前预生成查找表,省略内层循环的移位、位与操作开销,性能比朴素实现高2~3倍。
预先初始化查找表代码:
// 全局/静态查找表,初始化一次即可复用 static uint8_t bit_lut[256][8]; __attribute__((constructor)) void init_lut() { for (int val = 0; val < 256; val++) { for (int b = 0; b < 8; b++) { bit_lut[val][b] = (val >> b) & 1; } } }
主逻辑代码:
memset(sum, 0, buf_len * 8 * sizeof(uint8_t)); // 调整循环顺序提升缓存命中率:同一位置的字节跨所有缓冲区处理,sum访问局部性更好 for (int i = 0; i < buf_len; i++) { for (auto&& buf : buffers) { uint8_t val = buf[i]; sum[i*8 + 0] += bit_lut[val][0]; sum[i*8 + 1] += bit_lut[val][1]; sum[i*8 + 2] += bit_lut[val][2]; sum[i*8 + 3] += bit_lut[val][3]; sum[i*8 + 4] += bit_lut[val][4]; sum[i*8 + 5] += bit_lut[val][5]; sum[i*8 + 6] += bit_lut[val][6]; sum[i*8 + 7] += bit_lut[val][7]; } }
方案2:SIMD向量化优化(x86平台AVX2支持,性能提升5~10倍)
可以利用AVX2指令集一次性处理32个字节,将每个字节的8个比特分别提取到不同的SIMD通道后做向量累加,适合缓冲区长度较大的场景,编译器开启-mavx2参数即可编译。
内容的提问来源于stack exchange,提问作者n1r44
相关产品推荐
相关产品推荐

