2017-08-30 57 views
2

_mm256_blendv_pd()查看位置63,127,191和255中的位。是否有有效的方法將uint8_t的4個低位分散到AVX寄存器的這些位置?有4位,如何產生AVX寄存器的掩碼?

或者,是否有一種有效的方式來廣播這些位,這樣就像_mm256_cmp_pd()的結果一樣,在AVX寄存器的相應64位組件中重複每個位?

指令集是AVX2(Ryzen CPU,如果需要其他功能的話)。

+0

由於63,127,191和255不是2的冪,所以它們不能是用於指示位位置的掩碼。如果他們是索引到一個位向量,那麼你至少有255位處理。 'unit8_t'包含8位(因此是'8'),所以你問你是否可以用8位表示255位?這似乎不太可能。你需要糾正這個問題,然後才能得到有意義的答案。 –

+0

如果你是一對一,64,128和256是2的冪,所以它們可能是位掩碼,但是192不適合該模式(因爲它是64 + 128,但是這是兩位)所以...... –

+1

@DaleWilson,這是一個關於AVX(2)技術的問題,它運行256位向量。 'uint8_t'最初有4位。我想將它們移動到指定位置(您不明白:63,127,191和255是基於0的位位置,而不是掩碼)到256位AVX寄存器。 –

回答

2

最有效的方法是使用包含16個256位條目的查找向量,由uint-8索引。

+0

這是一個很好的解決方案,但需要16 * 32 = 512字節的緩存。 –

+1

I.e.在許多處理器上有兩條高速緩存行 - 而那些高速緩存行將是隻讀的,這對我們有很大的幫助。我敢打賭,當你編譯移位,掩碼和Ors時,必須將這些位分配到256位矢量表查找將運行得更快,即使它確實需要偶爾的緩存加載。但是,對於這種類型的問題,當然也一樣,「哪個更快」的唯一真正答案就是分析。然而,我描述的方法在代碼清晰度和可維護性方面明顯勝出。 –

+0

x86_64上的高速緩存行通常是64個字節,所以512個字節是8個高速緩存行。 –

2

顯而易見的解決方案:將這4位用作查找表的索引。你已經知道了,所以我們試試其他的東西吧。

基於變量移位的方法:將該字節廣播到每個qword中,然後將它左移{63,62,61,60},排列msb中的右邊位。沒有測試過這樣的事情:

_mm256_sllv_epi64(_mm256_set1_epi64x(mask), _mm256_set_epi64x(63, 62, 61, 60)) 

還有一個好處,由於負載不依賴於面膜,它可以擺脫循環。

這對Ryzen來說不一定是個好主意,內存中的256位加載的吞吐量比單獨的vpsllvq的吞吐量要高(這與Ryzen的大多數256b操作一樣是2微妙),但是在這裏我們也有vmovq(如果該字節不是來自向量寄存器的話)以及較寬的vpbroadcastq(再次2μops)。

根據具體情況,可能值得做或不做。這取決於。

2

假設uint8_t存在於通用寄存器中;的做法是:

  1. 使用PDEP於四個比特轉換爲4個字節(最高位)
  2. 傳遞從32位GPR四個字節到YMM的低部分寄存器
  3. 把值到位(位63,127,191,255)

於是我想出了兩個版本 - 一個使用內存和其他一個沒有:內存

方法:

.data 
    ; Always use the highest bytes of a QWORD as target/128 means 'set ZERO' 
    ddqValuesDistribution: .byte 3,128,128,128,128,128,128,128, 2,128,128,128,128,128,128,128, 1,128,128,128,128,128,128,128, 0,128,128,128,128,128,128,128 
.code 
    ; Input value in lower 4 bits of EAX 
    mov  edx, 0b10000000100000001000000010000000 
    pdep eax, eax, edx 
    vmovd xmm0, eax 
    vpshufb ymm0, ymm0, ymmword ptr [ddqValuesDistribution] 

在上的Haswell和SKYLAKE微架構5個微指令這一次出來。


無記憶變量方法(改進得益於@Peter科爾德):(!)

mov edx, 0b10000000100000001000000010000000 
    pdep eax, eax, edx 
    vmovd xmm0, eax 
    vpmovsxbq ymm0, xmm0 

在上的Haswell和SKYLAKE微架構和4個微指令這一個出來可以通過移動能夠進一步提高EDX中的面具變爲一個變量。
輸出與第一個版本不同(全部是1而不是最高位集合)。

+0

@ zx485:在Ryzen上pdep是6個uops。所以這些計數只適用於英特爾CPU。 –

+0

嘗試使用'vpmovsxbq'將每個字節的符號位複製到每個qword的高位56位。 –

+0

@PeterCordes:非常感謝。真的很棒的建議。令人遺憾的是,PDEP在Ryzen表現不佳。 – zx485