亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

AVX 2基于面罩的最有效的打包方法是什么?

AVX 2基于面罩的最有效的打包方法是什么?

C++
汪汪一只貓 2019-07-11 10:25:35
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個周期)。

我想出了這個方法,它使用一個壓縮LUT,它是768(+1填充)字節,而不是8k。它需要一個單一標量值的廣播,然后在每個車道上移動一個不同的量,然后隱藏到較低的3位,這提供了一個0-7 LUT。

這里是本質版本,以及構建LUT的代碼。

//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);
    }}

下面是MSVC生成的程序集:

  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



查看完整回答
反對 回復 2019-07-11
  • 3 回答
  • 0 關注
  • 847 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號