C SIMD:在数组中累积UINT64_T元素的爆米花
C++ SIMD: accumulate POPCOUNTs of uint64_t elements in an array
我试图使用SSE指令在数组中为uint64_t
整数累积POPCOUNT
s。
这是我的代码:
#include <emmintrin.h>
#include <nmmintrin.h>
#include <chrono>
int main()
{
uint64_t data[4] = {1,1,1,1};
uint64_t data2[4] = {1,0,1,0};
__m128i* ptr = (__m128i*) data;
__m128i* ptr2 = (__m128i*) data2;
int total = 0;
for (int i = 0; i < 2; ++i, ++ptr, ++ptr2)
total += popcount(_mm_and_si128(*ptr, *ptr2)); // This doesn't work
}
我需要在_mm_and_si128
输出上运行的POPCOUNT
函数的等效物,因此我可以将所有POPCOUNT
s累积到total
变量中。
我们拥有有关此主题的整个研究论文:使用AVX2指令进行更快的人群计数。尽管有标题,但它也涵盖了SSE。有关相关的软件库,请参见Hamming_Weight。它包括各种快速功能来执行此类工作。
简短的答案:您可以像这样使用Muła爆炸式函数:
__m128i popcount(__m128i v) {
const __m128i lookup = _mm_setr_epi8(
/* 0 */ 0, /* 1 */ 1, /* 2 */ 1, /* 3 */ 2,
/* 4 */ 1, /* 5 */ 2, /* 6 */ 2, /* 7 */ 3,
/* 8 */ 1, /* 9 */ 2, /* a */ 2, /* b */ 3,
/* c */ 2, /* d */ 3, /* e */ 3, /* f */ 4
);
__m128i low_mask = _mm_set1_epi8(0x0f);
__m128i lo = _mm_and_si128(v, low_mask);
__m128i hi = _mm_and_si128(_mm_srli_epi16(v, 4), low_mask);
__m128i popcnt1 = _mm_shuffle_epi8(lookup, lo);
__m128i popcnt2 = _mm_shuffle_epi8(lookup, hi);
return _mm_sad_epu8(_mm_add_epi8(popcnt1, popcnt2), _mm_setzero_si128());
}
popcount
调用的结果是由两个64位计数器制成的128位计数器,您必须添加。总结两个64位计数器可以在结束时节省计算时间。
POPCOUNT
与SSE寄存器不起作用。您需要将_mm_and_sil128
的结果保存到内存,然后在两个半部分使用POPCOUNT
(_mm_popcnt_u64
),因为POPCOUNT
指令最多仅限于64位操作数。
相关文章:
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 使用strcpy将char数组的元素复制到另一个数组
- 使用不带参数的函数访问结构元素
- 给定n个元素的m个集合.在C++中找到出现在最大集合数中的元素
- C++如何通过用户输入删除列表元素
- lower_bound()返回最后一个元素
- 基于多个条件处理地图中的所有元素
- 调整大小后指向元素值的指针unordered_map有效?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 使用函数"remove"删除重复元素
- 具有最大子序列大小的序列,每个元素都相同
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 如何将元素添加到数组的线程安全函数?
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- 我想访问std::unique_ptr中的一个特定元素
- 如何通过 getter 函数删除矢量的元素?
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 从控制台中删除最后打印的元素
- 擦除while循环中迭代的元素