【发布时间】:2014-08-29 15:54:08
【问题描述】:
我是第一次深入了解 SSE2 内在函数,但我不知道该怎么做。
我想将 4 个 int32 与 4 个其他 int32 进行比较,并计算有多少是相等的。 所以我读取了我的前 4 个 int32,将它们设置在 __m128i 中,对第二组执行相同操作,并使用 _mm_cmpeq_epi32 进行比较。
这将导致包含 4 个 int32 的 __m128i,每个 0xffffffff 或 0 取决于 int 是否相等。
但我不知道如何从生成的 __m128i 到 count 指定实际相等的数量。
谁能指出我正确的方向?
我正在拼凑的代码:
int* source = blah;
int* reference = otherblah;
// Load the 4 source int32's (they are actually 4 int32s apart)
__m128i first_4_int32s = _mm_set_epi32(*(source + 12), *(source + 8), *(source + 4), *(source));
// Load the 4 source int32's (also actually 4 int32s apart)
__m128i second_4_int32s = _mm_set_epi32(*(reference + 12), *(reference + 8), *(reference + 4), *(reference));
// Compare the int32's
__m128i result = _mm_cmpeq_epi32(first_4_int32s, second_4_int32s);
// Perform magic here that counts whether 0, 1, 2, 3 or all 4 ints were equal ?!?!
【问题讨论】:
-
请注意,像这样执行收集的负载会导致性能下降 - 如果您不能使用连续数据,最好还是坚持使用标量代码。
-
是的,您在这里执行的操作可能比按顺序执行要慢很多。因此,除非您可以更改内存访问模式,否则不要浪费时间对其进行矢量化。
-
您是只为 4 个值执行此操作,还是为一大堆值,但一次只为 4 个?让我知道,我很乐意写一个解决方案。除此之外,这里有几点。如果真的只有 4 个值,请考虑 _mm_packs_epi32,然后是 _mm_packs_epi16,然后是 _mm_movemask_epi8,然后是查找表,但标量版本可能更快。无论如何,您不应该像那样使用 _mm_set_epi32,而应该使用 _mm_load_ps 或 _mm_loadu_ps 将所有 4 个值一起加载。现在,如果您要为一大堆 4 元组执行此操作,您只需在 __m128i 中维护 4 个总和。
-
然后最后你可以将 4 个组件加起来为一个值。这可以通过移位和水平添加或减去单个组件来完成。无论如何,它只在最后完成一次。在分别对所有内容求和时,比较后您有两个可能的值。 0x00000000 或 0xFFFFFFFF。请记住 0xFFFFFFFF 也是
-1。因此,您可以做的是使用 _mm_sub_epi32 从当前总和中减去比较值。因此,电流减 0 保持电流不变。而电流减-1变成电流加1(减负就是加正)。
标签: count comparison sse intrinsics sse2