2012-08-08 37 views
-1

中的OpenCL代碼是這樣寫的OpenCL疑惑;如何將intrinsics轉換爲簡單的c語言?

void unpack_8bit_to_16bit(const __m128i a, __m128i& b0, __m128i& b1) 
{ 
     __m128i zero = _mm_setzero_si128(); 
     b0 = _mm_unpacklo_epi8(a, zero); 
     b1 = _mm_unpackhi_epi8(a, zero); 
} 

現在我想這個代碼轉換成C語言,這可能嗎?

+0

該代碼不是OpenCL它**是具有x86 SSE2整數內部指令的**標準C. – talonmies 2012-08-08 06:31:36

+0

是啊,對不起,我的意圖是將該代碼轉換爲OpenCL,但之前轉換爲C lang。,所以..我誤以爲thomas爲您的答覆 – Fakruddeen 2012-08-08 09:00:55

回答

2

正如評論中指出的那樣,這不是OpenCL代碼。然而,如果您的意思是如何將此代碼轉換爲 OpenCL,則矢量化的方法是使用矢量類型,例如float4(四個32位浮點數),double3(三個64位雙精度),long8(八個64比特整數)等等......甚至還有內置像四核(128位浮點),複雜雙打等硬核類型......

在你的情況下,你基本上想要的是解開一堆字節轉換爲16位字,分離輸入的低四元組和高四元組。你可以通過swizzling或明確計算每個向量來做到這一點,但也有另一種方法來做這個特定的計算 - OpenCL有一個向量分裂機制,它將任意向量類型分成兩個更低和更高的一半。這是這樣完成的:

float4 input = (float4)(4.3, 0.71, 9.1, 44.8); 
float2 inputLo = input.lo; // = (4.3, 0.71) 
float2 inputHi = input.hi; // = (9.1, 44.8) 

顯然,這是適合於您的問題,因爲所有你需要做的就是你的char16(16個8位字節)分成兩個較低和較高CHAR8的,並解釋這些CHAR8的作爲short8's(因爲你是解包),無論是通過投射或明確轉換。

請注意,這對於OpenCL來說是一個奇怪的問題 - 這種解包機制來自數據必須打包到SSE寄存器的方式,所以如果你想從8位元素切換到16位。在OpenCL中,這是沒有必要的,因爲您的矢量類型不承擔特定的數據安排(並且您可以很容易地從一種類型轉換爲另一種類型)。如果您的OpenCL內核恰好在支持SSE的處理器上執行,那麼內核編譯器會自動爲您打包和解包 - 希望最佳,如果您的代碼是理性的。

您不能在OpenCL中使用內部函數,因爲內核不會在x86和x64硬件上獨佔運行 - 它們也可以在GPU,FPGA和定製芯片上運行。相反,您使用的通用矢量類型會自動轉換爲編譯內核的平臺上正確的SIMD指令(實際上,它稍微複雜一點,但這是它的要點)。


鑑於您的最新評論,我會補充一點:如果你想在內部函數轉化爲簡單的C代碼,所有需要的是數據是如何打包到SSE寄存器的理解。從基本的角度來看,它是如何工作的:每個SSE寄存器都是128位寬,因此可以保存16個字節,8個字,4個長等等......你不能混合這些類型,所以你不能2個字節和7個字,每個內在函數都假設一個特定的類型(例如,您可能想要寄存器中每個64位雙精度的平方根,或每個32位浮點數的平方根!清楚表明您選擇哪種類型) 。

這些類型總是連續的,所以說你想將一個8字的向量轉換成兩個4字長的向量,即「解包」它可以對其進行32位計算,這意味着你想要從去:

[16-bit][16-bit][16-bit][16-bit][16-bit][16-bit][16-bit][16-bit] 

[32-bit][32-bit][32-bit][32-bit] & [32-bit][32-bit][32-bit][32-bit] 

顯然你不能只重用寄存器,因爲兩個16位字將得到合併成一個單一的32位的值,它會產生垃圾。相反,您必須有條不紊地將每個16位字拉出來,將其轉換爲32位長,並將其放入新寄存器--SSE在硬件中執行所有操作(內部調用適當的指令)。

在您的具體情況下,您有一個包含16個字節的寄存器,並且您希望將數據「輸出」到另外兩個寄存器中,而這些寄存器將包含8個字。所以,如果你輸入寄存器包含a0..a15(這些都是字節),那麼你將有:

b0 = (word)a_0..(word)a_7 
b1 = (word)a_8..(word)a_15 

您可以在C使用數組做到這一點,「模擬」的SSE寄存器(你可以做花哨包含每個可能的矢量的聯合,這個聯合適合於一個寄存器,或者只是硬編碼不同的數組類型並相互轉換)。

僅供參考,請參閱this,它對此有所解釋(我也建議您閱讀SSE寄存器如何工作,因爲這是包裝存在的原因以及它的重要性)。

+0

...解決方案的問題是,我有一個char *和我需要從中取出128位。 SSE內在函數如下: char * I; __m128i xmm1; xmm1 = _mm_loadsi128((__ m128i *)(I)); – Fakruddeen 2012-08-09 09:45:01

+0

@ user1583722那麼這是什麼問題,你只是簡單地從char * l中讀取128位(= 16字節)並將它們放入一個寄存器,如果你想將它轉換爲普通的C,那麼memcpy就是一個簡單的事情到「假」XMM寄存器 - 基本上,在軟件中實現_mm_loadsi128。 – Thomas 2012-08-09 21:06:09