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 关注
- 801 浏览
添加回答
举报
0/150
提交
取消