继承我的代码:
#include <stdio.h>
#include <CL/cl.h>
#include <CL/cl_platform.h>
int main(){
cl_float3 f3 = (cl_float3){1, 1, 1};
cl_float3 f31 = (cl_float3) {2, 2, 2};
cl_float3 f32 = (cl_float3) {2, 2, 2};
f3 = f31 + f32;
printf("%g %g %g \n", f3.x, f3.y, f3.z);
return 0;
}
使用gcc 4.6进行编译时,会产生错误
test.c:14:11: error: invalid operands to binary + (have ‘cl_float3’ and ‘cl_float3’)
对我来说很奇怪,因为OpenCL Specification在第6.4节中除了这个,增加了两个floatn
。我是否需要包含任何其他标题?
但更奇怪的是,在使用-std=c99
进行编译时,我会收到类似
test.c:16:26: error: ‘cl_float3’ has no member named ‘x’
..适用于所有组件(x,y和z)......
答案 0 :(得分:6)
结构下标编译问题的原因可以在AMD SDK中的标准实现中看到。
如果查看AMD工具包中的<CL/cl_platform.h>
标题,您可以看到如何定义结构。
typedef cl_float4 cl_float3;
typedef union
{
cl_float CL_ALIGNED(16) s[4];
#if (defined( __GNUC__) || defined( __IBMC__ )) && ! defined( __STRICT_ANSI__ )
__extension__ struct{ cl_float x, y, z, w; };
....
#endif
}cl_float4;
使用#if
调用gcc时,将忽略--std=c99
子句。
要使代码与--std = c99一起使用,您可以将f3.x
的引用替换为f3.s[0]
,依此类推。
答案 1 :(得分:5)
OpenCL程序由两部分组成。
你们对这两者感到困惑,并试图在主机代码中使用内核语言的功能。
答案 2 :(得分:2)
cl_float.v
是另一种选择:
#include <assert.h>
#include <CL/cl.h>
int main(void) {
cl_float4 f = {{1, 2, 3, 4}};
cl_float4 g = {{5, 6, 7, 8}};
cl_float4 h;
h.v4 = f.v4 + g.v4;
assert(h.s[0] == 6);
assert(h.s[1] == 8);
return EXIT_SUCCESS;
}
可以运行:
gcc -std=c89 -Wall -Wextra tmp.c -lOpenCL && ./a.out
在Ubuntu 16.10,gcc 6.2.0。
v
在Linux GCC x86中通过GCC vector extensions定义。
#if defined( __SSE__ )
[...]
#if defined( __GNUC__ )
typedef float __cl_float4 __attribute__((vector_size(16)));
[...]
#define __CL_FLOAT4__ 1
然后:
typedef union
{
[...]
#if defined( __CL_FLOAT4__)
__cl_float4 v4;
#endif
}cl_float4;
不确定这种ifdefs
的弹幕是Khronos的一个好举动,但它就是我们所拥有的。
我建议您始终使用.s[0]
,这是最便携的选项。如果我们专注于GPU,我们不应该加速主机SIMD ......
C11匿名结构
错误error: ‘cl_float3’ has no member named ‘x’
因为https://stackoverflow.com/a/10981639/895245
更确切地说,此功能称为"anonymous struct",它是在C11中标准化的扩展。
因此理论上它也应该与-std=c11
一起使用,但它目前还没有,因为CL标题没有更新以检查C11,另请参阅:https://github.com/KhronosGroup/OpenCL-Headers/issues/18