我正在寻找一种方法来找到无符号32位整数(类似于epu16)的最小值及其在sse中的位置。我知道我可以通过一系列的EPU32和洗牌/换班找到最小值,但这并不能让我得到这个位置。
有没有什么酷的方法?

最佳答案

也许有一种更聪明的方法,但现在有一种暴力的方法:

#include <stdio.h>
#include <smmintrin.h> // SSE4.1

int main(void)
{
    __m128i v = _mm_setr_epi32(42, 1, 43, 2);

    printf("v     = %vlu\n", v);

    __m128i vmin = v;

    vmin = _mm_min_epu32(vmin, _mm_alignr_epi8(vmin, vmin, 4));
    vmin = _mm_min_epu32(vmin, _mm_alignr_epi8(vmin, vmin, 8));
                                                   // get min value in all elements of vmin

    printf("vmin  = %vlu\n", vmin);

    __m128i vmask = _mm_cmpeq_epi32(v, vmin);      // set min element(s) in mask to -1,
                                                   // all others to 0 [1]

    printf("vmask = %vld\n", vmask);

    int16_t mask = _mm_movemask_epi8(vmask);       // get mask as scalar [2]

    printf("mask  = %#x\n", mask);

    int pos = __builtin_ctz(mask) >> 2;            // convert scalar mask to index [3]

    printf("pos   = %d\n", pos);

    return 0;
}

如果可以使用设置在最小元素位置的掩码,则可以仅在[1]处停止,否则继续[3]以获取(最低有效)最小元素的索引。
还要注意__builtin_ctz是gcc特有的内部函数(尽管它也可以在其他gcc兼容的编译器中找到)。如果您使用的是msvc,那么您将需要使用等效的Microsoft内部函数(_BitScanForward)。

09-11 05:03