AVX 2基于面罩的最有效的打包方法是什么?如果您有一個輸入數組和一個輸出數組,但是您只想編寫那些通過某種條件的元素,那么在AVX 2中最有效的方法是什么?我在SSE中見過這樣的操作:(來自:https:/ulinenoise.files.wordpress.com/2015/03/gdc 2015_afredriksson_simd.pdf)__m128i LeftPack_SSSE3(__m128 mask, __m128 val){
// Move 4 sign bits of mask to 4-bit integer value.
int mask = _mm_movemask_ps(mask);
// Select shuffle control data
__m128i shuf_ctrl = _mm_load_si128(&shufmasks[mask]);
// Permute to move valid values to front of SIMD register
__m128i packed = _mm_shuffle_epi8(_mm_castps_si128(val), shuf_ctrl);
return packed;}對于4寬的SSE來說,這似乎很好,因此只需要16項LUT,但是對于8寬的AVX,LUT變得相當大(256個條目,每個條目32字節,或8k)。我感到驚訝的是,AVX似乎沒有一個簡化這一過程的指示,例如一個帶包裝的蒙面商店。我認為,如果對左邊設置的符號位#進行一些調整,您可以生成必要的置換表,然后調用mm256_permutevar8x32_ps。但我認為這也是相當多的指示。有人知道用AVX 2做這件事有什么竅門嗎?或者什么是最有效的方法?謝謝
3 回答

翻翻過去那場雪
TA貢獻2065條經驗 獲得超14個贊
如果您的目標是AMD Zen,這個方法可能是首選的,因為非常慢的pdepandpext在ryzen(每個周期18個周期)。
//Generate Move mask via: _mm256_movemask_ps(_mm256_castsi256_ps(mask)); etc__m256i MoveMaskToIndices(u32 moveMask) { u8 *adr = g_pack_left_table_u8x3 + moveMask * 3; __m256i indices = _mm256_set1_epi32(*reinterpret_cast<u32*>(adr));//lower 24 bits has our LUT // __m256i m = _mm256_sllv_epi32(indices, _mm256_setr_epi32(29, 26, 23, 20, 17, 14, 11, 8)); //now shift it right to get 3 bits at bottom //__m256i shufmask = _mm256_srli_epi32(m, 29); //Simplified version suggested by wim //shift each lane so desired 3 bits are a bottom //There is leftover data in the lane, but _mm256_permutevar8x32_ps only examines the first 3 bits so this is ok __m256i shufmask = _mm256_srlv_epi32 (indices, _mm256_setr_epi32(0, 3, 6, 9, 12, 15, 18, 21)); return shufmask;}u32 get_nth_bits(int a) { u32 out = 0; int c = 0; for (int i = 0; i < 8; ++i) { auto set = (a >> i) & 1; if (set) { out |= (i << (c * 3)); c++; } } return out;}u8 g_pack_left_table_u8x3[256 * 3 + 1];void BuildPackMask() { for (int i = 0; i < 256; ++i) { *reinterpret_cast<u32*>(&g_pack_left_table_u8x3[i * 3]) = get_nth_bits(i); }}
lea ecx, DWORD PTR [rcx+rcx*2] lea rax, OFFSET FLAT:unsigned char * g_pack_left_table_u8x3 ; g_pack_left_table_u8x3 vpbroadcastd ymm0, DWORD PTR [rcx+rax] vpsrlvd ymm0, ymm0, YMMWORD PTR __ymm@00000015000000120000000f0000000c00000009000000060000000300000000
- 3 回答
- 0 關注
- 847 瀏覽
添加回答
舉報
0/150
提交
取消