(Jestem zainteresowany tylko w 1. 3 komponentów)Najlepszy sposób obliczyć max maskę SSE var
Na przykład:
[ 1 2 3 ? ]
powinna produkować [ 0 0 -1 ? ]
Ponadto, ważne jest, aby mieć tylko jeden " nieco”ustawić tak, aby:
[ 1 2 2 ? ]
nie powinien produkować [ 0 -1 -1 ? ]
ale raczej
[ 0 -1 0 ? ]
lub [ 0 0 -1 ? ]
(nie ma znaczenia, który z nich)
Późniejsza (złe) rozwiązanie jest możliwe, na przykład poprzez ekstrakcję poziome max i porównanie z oryginałem:
__m128 abcd; // input
__m128 ccac = _mm_shuffle_ps(abcd, abcd, 0x8A);
__m128 abcd_ccac = _mm_max_ps(abcd, ccac);
__m128 babb = _mm_shuffle_ps(abcd, abcd, 0x51);
__m128 abcd_ccac_babb = _mm_max_ps(abcd_ccac, babb);
__m128 mask = _mm_cmpeq_ps(abcd, abcd_ccac_babb);
Być może niektórzy bitowe operacje, aby pozbyć się duplikatów zestaw bitów?
Aktualizacja:
Kontynuacja, zrobiłem kolejny (złego) rozwiązanie.
Kluczem jest porównanie każdego komponentu z innym, unikanie równań równości (nie mając w innym miejscu a >= b
i b >= a
).
a > b & a >= c
b > c & b >= a
c > a & c >= b
otrzymując:
([ a b c ? ] > [ b c a ? ]) & ([ a b c ? ] >= [ c a b ? ])
i w postaci kodu:
__m128 abcd; // input
__m128 bcad = _mm_shuffle_ps(abcd, abcd, 0xC9);
__m128 gt = _mm_cmpgt_ps(abcd, bcad);
__m128 cabd = _mm_shuffle_ps(abcd, abcd, 0xD2);
__m128 ge = _mm_cmpge_ps(abcd, cabd);
__m128 mask = _mm_and_ps(gt, ge);
to nie działa w przypadku [ x x x ? ]
(produkuje [ 0 0 0 ? ]
).
Zbliżanie się :-)
Jakieś pomysły?
Aktualizacja:
Obecnie używam następujące rozwiązanie:
__m128 abcd; // input
__m128 bcad = _mm_shuffle_ps(abcd, abcd, 0xC9);
__m128 gt = _mm_cmpgt_ps(abcd, bcad);
__m128 cabd = _mm_shuffle_ps(abcd, abcd, 0xD2);
__m128 ge = _mm_cmpge_ps(abcd, cabd);
__m128 and = _mm_and_ps(gt, ge);
__m128i bits = _mm_setr_epi32(_mm_movemask_ps(and), -1, -1, -1);
__m128i dirt = _mm_cmpeq_epi32(bits, _mm_setzero_si128());
__m128i mask = _mm_or_si128(dirt, _mm_castps_si128(and));
Nie widzę żadnego wydajnego ani eleganckiego sposobu robienia tego w tej chwili - wszystko, co mogę wymyślić do tej pory, to wyodrębnienie 4 bitów MS z 'maski' przy użyciu' _mm_movemask_ps', a następnie przetworzenie tego, aby uzyskać unikalny wartość jednobitowa, którą można następnie przekonwertować z powrotem na wektor maski. –
Czy musisz zrobić to sekwencyjnie, czy możesz to zrobić niezależnie, na przykład, jeśli masz tablicę 2D podobną do {{1,2,3}, {4,5,6}, ...} czy możesz znaleźć maksimum dla {1,2,3} i {4,5,6} niezależnie? Jeśli możesz to zrobić niezależnie dla różnych zestawów liczb, to będzie to bardziej efektywne dzięki SIMD. –
@PaulR '_mm_movemask_ps' jako podejście do operacji bitowych jest bardzo mile widziane. –