2014-01-08 24 views
2

我想在我的C代碼中使用英特爾的PCLMULQDQ指令和內聯彙編,用於乘以GF(2^n)中元素的兩個多項式。編譯器是GCC 4.8.1。 多項式存儲在uint32_t(6個字段大)的數組中。C inline asm中的PCLMULQDQ指令

我已經檢查過網頁如何正確使用PCLMULQDQ指令或CLMUL指令集,但沒有找到任何好的文檔。

我真的很感激一個簡單的例子,在C和asm中如何將兩個簡單多項式與指令相乘。有人知道該怎麼做嗎?

此外,是否有任何先決條件(除了有能力的處理器),像包括庫,編譯器選項等?

+0

快速搜索yielded http://download-software.intel.com/sites/default/files/article/165685/clmul-wp-rev-2.01-2012-09-21.pdf –

回答

0

我已經找到了解決方案。因此備案:

void f2m_intel_mult(
    uint32_t t, // length of arrays A and B 
    uint32_t *A, 
    uint32_t *B, 
    uint32_t *C 
) 
{ 
    memset(C, 0, 2*t*sizeof(uint32_t)); 
    uint32_t offset = 0; 
    union{ uint64_t val; struct{uint32_t low; uint32_t high;} halfs;} prod; 

    uint32_t i; 
    uint32_t j; 
    for(i=0; i<t; i++){ 
     for(j=0; j<t; j++){ 

      prod.halfs.low = A[i]; 
      prod.halfs.high = 0; 
      asm ("pclmulqdq %2, %1, %0;" 
      : "+x"(prod.val) 
      : "x"(B[j]), "i"(offset) 
      ); 

      C[i+j] = C[i+j]^prod.halfs.low; 
      C[i+j+1] = C[i+j+1]^prod.halfs.high; 
     } 
    } 
} 

我認爲這是可能使用64位寄存器pclmulqdq,但我無法找出如何得到這個與內聯彙編工作。有人知道嗎?
儘管如此,也可以對intrinsics做同樣的事情。 (如果你想要的代碼只是問)
此外,如果你知道數組的大小t,可以用Karatsuba進一步優化計算。

+0

[編譯器輸出這個](https://godbolt.org/g/eaQrRx)在很多方面都很糟糕。首先,每個'pclmul'都被一個'movq'包圍,以將一個64位整數寄存器複製到xmm寄存器的低位一半。其次,'xor'操作使用32位操作數大小,而不是合併成一個64位xor與一個內存目標。 –

+0

不,沒有任何形式的pclmul在整數/ gp寄存器上運行,[僅限xmm]。將128位數據直接加載到SSE向量中會更加高效,並使用具有不同立即偏移的'pclmul'來完成乘法的不同部分。如果你需要將'A'零擴展到64位元素,你可以在SSE中用'punpckldq'和零寄存器來完成。 (或者SSE4.1'pmovzx')。其實你對B​​也是這樣,但是隱含的。 –

+0

您應該使用SSE操作將XOR轉換爲'C'。 (從C加載,'pxor',存儲回來)。無論如何,你絕對應該使用intrinsics而不是inline asm。您的內聯匯款是正確和安全的,但您失去了很多業績。 –