我一直在 C# 中使用 simd 進行學習/實驗,并遇到了這個問題:給定兩個包含 4 x uint64 的 256 位向量,將它們重新a = <0,2,4,6>, b = <1,3,5,7>排列成c = <0,1,2,3>, d = <4,5,6,7>.
我當前的解決方案使用兩個排列并解壓低高,我確信必須有更好的方法來做到這一點,只使用兩個排列或更好的解壓低/高。有沒有更好的方法來做到這一點?
Vector256<ulong> a = Vector256.Create((ulong)0, 2, 4, 6);
Vector256<ulong> b = Vector256.Create((ulong)1, 3, 5, 7);
Vector256<ulong> low = Avx2.UnpackLow(a, b);
Vector256<ulong> high = Avx2.UnpackHigh(a, b);
var c = Avx2.Permute2x128(low, high, 0b_00_10_00_00);
var d = Avx2.Permute2x128(low, high, 0b_00_11_00_01);
// Translated to C - I haven't tried running it.
//given __m512i a, b, low, high, c, d
low = _mm256_unpacklo_epi64(a,b); // 0,1,4,5
high = _mm256_unpackhi_epi64(a,b); // 2,3,6,7
c = _mm256_permute2x128_si256(low,high); // 0,1,2,3
d = _mm256_permute2x128_si256(low,high); // 4,5,6,7
uj5u.com熱心網友回復:
這是一個稍微好一點的方法:
Vector256<ulong> a = Vector256.Create( (ulong)0, 2, 4, 6 );
Vector256<ulong> b = Vector256.Create( (ulong)1, 3, 5, 7 );
Vector256<ulong> low = Avx2.UnpackLow( a, b );
Vector256<ulong> high = Avx2.UnpackHigh( a, b );
var d = Avx2.Permute2x128( low, high, 0b_00_11_00_01 );
var c = Avx2.InsertVector128( low, high.GetLower(), 1 );
與 Intel CPU 上的代碼速度相同。但在 AMD 上稍快一些:在 Zen 2 或 Zen 3 等 CPU 上,vinserti128指令只有 1 個延遲周期,vperm2i128指令有 3 個延遲周期。
uj5u.com熱心網友回復:
如果您在本地對 shuffle 埠比其他埠有更大的壓力,您可以將一個 shuffle 換成兩個混合,就像這樣(抱歉,這只是 C/C ,但我假設您可以在需要時將其轉換為 C#):
__m256i t0 = _mm256_unpacklo_epi64(a, b);
__m256i t1 = _mm256_unpackhi_epi64(a, b);
__m256i swap = _mm256_permute2x128_si256(t0, t1, 0x21);
c = _mm256_blend_epi32(t0, swap, 0xf0);
d = _mm256_blend_epi32(swap, t1, 0xf0);
請注意,clang 實際上將其“優化”回具有兩個的變體vperm2f128(但這可能取決于背景關系):https ://godbolt.org/z/499abhWYb (檢查interleave2方法)。
如果您想將結果存盤到記憶體中(可能在對其進行一些其他操作之后),那么在某些情況下使用一組vextracti128_m128也可能是一種選擇(使用更多存盤操作但保存隨機/混合操作)。
uj5u.com熱心網友回復:
如果沒有 AVX-512 for 2x ,這看起來很合理vpermt2q。
AVX2 沒有任何粒度小于 128 位vperm2i128(又名_mm256_permute2x128_si256)的 2 輸入車道交叉洗牌。
并且vpermq為混合設定洗牌每個輸入可能會 4x 洗牌 2xvpblendd所以這并不是更好。
也許我錯過/忘記了一個更聰明的技巧,但我不希望你能做得更好。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/518528.html
上一篇:將大類分解為更小的方法
