Opencl 向量化我的标量函数
假设我想计算一个升余弦。我可以有一个宏来定义cos(x)(0.5f+0.5f*cos(x)),但是为了我的问题,我想把它变成一个函数,如下所示:Opencl 向量化我的标量函数,opencl,vectorization,Opencl,Vectorization,假设我想计算一个升余弦。我可以有一个宏来定义cos(x)(0.5f+0.5f*cos(x)),但是为了我的问题,我想把它变成一个函数,如下所示: float cos_raised(float x) { return 0.5f + 0.5f * cos(x); } float{N:} cos_raised_float{N:}(float{N:} x) { return 0.5f + 0.5f * cos(x); } 这可以很好地工作,但只有一个浮点输入,当它可以很容易地矢量化时
float cos_raised(float x)
{
return 0.5f + 0.5f * cos(x);
}
float{N:} cos_raised_float{N:}(float{N:} x)
{
return 0.5f + 0.5f * cos(x);
}
这可以很好地工作,但只有一个浮点输入,当它可以很容易地矢量化时。如何正确地对其进行矢量化,并使其接受float2/3/4/8/16作为输入和输出,而不复制函数体(这是一个简单的示例,但对于更复杂的函数,我需要知道这一点)
编辑:我想我是在问如何生成gentype函数?但是,仅仅键入
gentype
是行不通的。IIRC:遗憾的是,“gentype”是一个仅存在于OpenCL文档中的概念,它实际上不是一种允许您自己创建泛型/模板式函数的语言功能。这意味着没有简单的方法来做你想做的事情,你可能需要使用一些预处理器的魔法来最小化代码重复。例如,请参阅此SO线程:它提供了比我更多的知识。如果编译器在进行矢量化之前将所有函数调用内联,那么您就可以完成所有设置。顺便说一句,矢量化可能只在CPU执行时需要,因为现在大多数GPU都是标量的。由于OpenCL内核是在运行时编译的,您可以在内核的开头添加额外的代码行。我会使用一个模板函数(例如,存储在单独的文本文件中),如下所示:
float cos_raised(float x)
{
return 0.5f + 0.5f * cos(x);
}
float{N:} cos_raised_float{N:}(float{N:} x)
{
return 0.5f + 0.5f * cos(x);
}
因为我更熟悉Python,所以我使用它的语法在字符串中指定占位符,即
{N:}
。您必须为主机代码的语言找到类似的东西。此后,只需在2、3、4、8和16之间建立一个循环,每次填写{N:}
。这将为您提供五个需要添加到内核代码开头的额外字符串。不利的一面是,您必须想出一些方法,在主内核代码中指明所有这些生成的函数应该插入的位置。它们需要出现在所有#pragma XXX:enable
语句之后。之后,您的内核可以调用任何版本,例如cos\u-raised\u-float4
内核中会有一个cos\u-raised
版本,还是多个版本,即同时有一个float2
和一个float4
版本?如果总是只有一个版本,那么在构建内核时定义几个宏就行了。什么宏?我的意思是,让你的内核只在float cos_-rised(floatN x)
的版本上使用,但是你不知道在你的程序实际运行之前,floatN将是什么。此场景适用于将所有函数矢量化以使用相同的矢量宽度,但仅在运行时定义矢量宽度的情况。如果是这种情况,您可以使用clBuildProgram
的options
参数,并传递类似“-D floatN=float2”
的内容。这样,您的代码中就有一个单一版本的函数,它可以处理floatN
中的任何类型。这够了吗?哦,我明白了。这是一个有趣的想法,但还不够笼统,因为我可能想把它混在一起。怎么做?因为它只是用float4输入cos_raised(),无法编译。对不起,我不理解你的问题。请再说一遍,我准备好了吗?我该怎么做才能让它像这样工作?因为它不会编译。对不起,我误读了。如果希望函数的版本采用向量类型,则需要编写每个版本。