假設我有8個SSE寄存器,枚舉爲r0,r1,r2,...,r7,並且每個都包含8個16位整數。我想創建一個新的寄存器,其中包含8個寄存器中的第i個元素,從r0開始,到r7。換句話說,我想獲得一個寄存器具有以下內容:從多個寄存器中收集特定元素並存儲到一個寄存器
r0[i],r1[i],r2[i],r3[i],r4[i],r5[i],r6[i],r7[i]
會如何,使用SSE(或AVX)做些什麼呢?
謝謝!
請注意,索引i不是常數,而是在運行時計算的。
假設我有8個SSE寄存器,枚舉爲r0,r1,r2,...,r7,並且每個都包含8個16位整數。我想創建一個新的寄存器,其中包含8個寄存器中的第i個元素,從r0開始,到r7。換句話說,我想獲得一個寄存器具有以下內容:從多個寄存器中收集特定元素並存儲到一個寄存器
r0[i],r1[i],r2[i],r3[i],r4[i],r5[i],r6[i],r7[i]
會如何,使用SSE(或AVX)做些什麼呢?
謝謝!
請注意,索引i不是常數,而是在運行時計算的。
這似乎是一個有趣的挑戰。如果你需要做到這一點在你的算法,它的時間去思考怎麼回事組織的事情,所以你不要做只是這一點,而不是像一個整體的8x8轉保羅的R意見建議。
我想的有點像pshufb
爲每個寄存器設置
xmmN[N] = old_xmmN[i]; // with other elements zeroed.
你必須洗牌口罩的表,並使用table[ (i-N) & 7]
爲shufflign xmmN
。或者,在零之前/之後重複洗牌蒙版,您可以使用從table[i]
開始的8個連續蒙版。 (所以你計算的地址轉換成註冊一次,並使用增加的位移。
然後POR
寄存器一起在樹上。(實際上,選擇第一POR
操作數和前兩個PSHUFB
年代後權安排,所以合併可與洗牌重疊。)
你可能被存儲到內存中,然後重裝獲得更好的吞吐量。(但也許更糟糕的等待時間,因爲店裏轉發延遲,這將導致的)。
rdi = tmp buffer
switch(i) {
case 0:
movd [rdi], xmm0
movd [rdi+2], xmm1
...
movd [rdi+14], xmm8 // note: writes all the way to [rdi+17]. use pextrw to avoid that.
break;
case 1:
pextrw [rdi], xmm0, 1; // SSE4.1 for memory dest pextrw
pextrw [rdi+2], xmm1, 1
...
break;
case 2:
same, but with imm8 = 2;
break;
...
}
movdqa xmm0, [rdi] ;// ~10 cycle store-forwarding stall
你想要做什麼你所描述的將會非常慢你試圖做轉置什麼的? – Mysticial 2014-10-10 05:53:21
你可以用7個PSHUFB指令做到這一點,但如果你加入你想通過這樣來實現的,因爲有可能是一個更好的整體解決方案是什麼一番解釋可能會更好。 – 2014-10-10 06:08:26
感謝您的回覆。很難解釋,但原則上我使用SSE逐列計算矩陣。結果是矩陣的最後一列和最後一行。我已經通過使用8個16位值的矢量向量化該方法,以便逐列地計算矩陣。我已經將矩陣的列長度(clen)填充爲8的倍數,這樣我就可以每列執行8次矢量計算。我總是覆蓋計算,即在內存中我總是隻有前一列的結果。在計算結束時,結果是最後一列(我想要的)。 – Tomas 2014-10-10 11:04:31