OpenCL怀疑;如何将内部函数转换成简单的c语言?

OpenCL怀疑;如何将内部函数转换成简单的c语言?,opencl,Opencl,在OpenCL中,代码是这样编写的 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语言,有可能吗?如注

在OpenCL中,代码是这样编写的

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语言,有可能吗?

如注释中所述,这不是OpenCL代码。但是,如果您的意思是如何将此代码转换为OpenCL,那么向量化的方法是使用向量类型,例如float4 4个32位浮点、double3 3个64位double、long8 8个64位整数等。。。甚至还有内置的硬核类型,如四位128位浮点、复数双精度等

在您的例子中,您基本上想要的是将一组字节解压成16位字,将输入的低位和高位四元组分开。您可以通过滑动或显式计算每个向量来实现这一点,但也有另一种方法来实现这一特定的计算-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十六个8位字节拆分为两个更低和更高的char8,并将这些char8解释为short8,因为您正在通过强制转换或显式转换来解包

请注意,对于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]

显然,您不能仅仅重用寄存器,因为两个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寄存器,您可以使用包含适合寄存器的每个可能向量的并集来实现这一点,或者只是硬编码不同的数组类型并相互转换


作为参考,请参阅,这解释了一点,我还建议您阅读SSE寄存器的工作原理,因为这就是打包存在的原因和它的重要性。

该代码不是OpenCL,而是带有x86 SSE2整数内在指令的标准C。是的,对不起,我的目的是将该代码转换为OpenCL,但在转换为C语言之前,请先将其转换为C语言,因此。。我把你的回答错当成了汉克斯·托马斯。。。解决方案的问题是,我有一个char*,需要从中取出128位。SSE内部函数类似于:char*I__m128i-xmm1;xmm1=_mm_载荷i128__m128i*I@用户1583722问题是什么,你只需从char*l中读取128位=16字节并将它们放入寄存器,如果你想将其转换为普通的C,只需将其存储到一个伪XMM寄存器中即可——基本上,在软件中实现_mm_loadsi128。
b0 = (word)a_0..(word)a_7
b1 = (word)a_8..(word)a_15