2016-11-25 66 views
3

我試圖找到一種更有效的方法來「旋轉」或將avx _m256矢量中的32位浮點值向右或向左移動一個地方。Shuffle AVX 256矢量元素左移/右移1位C內部函數

使得:

A7,A6,A5,A4,A3,A2,A1,A0

變得

0,A7,A6,A5,A4,A3,A2,A1

(我不介意,因爲我反正更換單元中的數據丟失。)

我已經查看了這個線程:Emulating shifts on 32 bytes with AVX 但我不雷爾y理解正在發生的事情,並且它不會解釋_MM_SHUFFLE(0,0,3,0)作爲輸入參數的功能。


我試圖優化此代碼:

_mm256_store_ps(temp, array[POS(ii, jj)]); 
_mm256_store_ps(left, array[POS(ii, jj-1)]); 

tmp_array[POS(ii, jj)] = _mm256_set_ps(left[0], temp[7], temp[6], temp[5], temp[4], temp[3], temp[2], temp[1]); 

我知道一旦一個轉變是在地方,我可以用插入來代替剩餘的細胞。我覺得這樣做會更有效率,然後拆開浮動陣列並重建。

- 我還希望能夠左右移動,因爲我需要在別處執行類似的操作。

任何幫助,非常感謝!謝謝!

+1

我們稱之爲洗牌,因爲你四處移動元素,不移動或旋轉的內部元件的鑽頭。 –

+0

感謝您的術語更正,恰當地更名問題! – MishMash95

+1

什麼是緊接在前面的代碼,填充什麼將會被移動,以及緊接着的將使用移位結果的代碼是什麼?也許外部部件可以集成到優化工作中。 –

回答

3

對於AVX2

使用VPERMPS做到在一個車道交叉排指令。

rotated_right = _mm256_permutevar8x32_ps(src, _mm256_set_epi32(0,7,6,5,4,3,2,1)); 

對於AVX(不包括AVX2)

既然你說的數據從內存中已經到來,這可能是件好事:

  • 使用未對齊的負荷得到將7個元素放在正確的位置,解決所有車道穿越問題。
  • 然後將纏繞的元素混合到另一個元素的向量中。
  • 要獲取包含就地混合的元素,可以使用廣播負載將其置於高位。 AVX可以在一個VBROADCASTPS指令中廣播加載(所以set1()便宜),儘管它確實需要Intel SnB和IvB(唯一兩個帶有AVX而不是AVX2的Intel微體系結構)上的shuffle端口。 (見標籤維基PERF的鏈接。

INSERTPS上XMM目的地唯一的工作,並不能達到高通道。

也許你可以使用VINSERTF128這樣做最終使他人不對齊的負載你想要的元素作爲上層車道中的高層元素(在低車道有一些無關注的載體)。

這個編譯,但沒有測試。

__m256 load_rotr(float *src) 
{ 
#ifdef __AVX2__ 
    __m256 orig = _mm256_loadu_ps(src); 
    __m256 rotated_right = _mm256_permutevar8x32_ps(orig, _mm256_set_epi32(0,7,6,5,4,3,2,1)); 
    return rotated_right; 
#else 
    __m256 shifted = _mm256_loadu_ps(src + 1); 
    __m256 bcast = _mm256_set1_ps(*src); 
    return _mm256_blend_ps(shifted, bcast, 0b10000000); 
#endif 
} 

the code + asm on Godbolt

+2

再次感謝您的幫助!我嘗試了AVX2方法,並且在我自己的機器上本地運行了極其可怕的操作 不幸的是,我意識到我的分發環境只有普通的AVX,另一種方法是使用loadu雖然我已經從你的回覆中學到了很多東西,所以謝謝你的時間:)!但是,它比我在實施時已經做的更慢了30%左右 – MishMash95