2012-08-08 39 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