5

Here's my code:

#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;
}

When compiling with gcc 4.6, it produces the error

test.c:14:11: error: invalid operands to binary + (have ‘cl_float3’ and ‘cl_float3’)

Very strange to me, because the OpenCL Specification demontrates in section 6.4 just that, an addition of two floatn. Do I need to include any other headers?

But even more strange is that when compiling with -std=c99 I get errors like

test.c:16:26: error: ‘cl_float3’ has no member named ‘x’

..for all components (x, y and z)...

einpoklum
  • 118,144
  • 57
  • 340
  • 684
TeaOverflow
  • 2,468
  • 3
  • 28
  • 40

3 Answers3

6

The reason for the compilation problem with structure subscripts can be seen in the implementation of the standard in the AMD SDK.

If you look at the <CL/cl_platform.h> header from AMD toolkit you could see how the structures are defined.

 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;

The #if clause is ignored when gcc is invoked with --std=c99.

To make your code work with --std=c99 you could replace references to f3.x with f3.s[0] and so on.

Dima Chubarov
  • 16,199
  • 6
  • 40
  • 76
5

OpenCL programs consist of two parts.

  1. A program which runs on the host. This is normally written in C or C++, but it's nothing special except that it uses the API described in sections 4 & 5 of the OpenCL Specification.
  2. A kernel which runs on the OpenCL device (normally a GPU). This is written in the language specified in section 6. This isn't C, but it's close. It adds things like vector operations (like you're trying to use). This is compiled by the host program passing a string which contains the kernel code to OpenCL via the API.

You've confused the two, and tried to use features of the kernel language in the host code.

Paul S
  • 7,645
  • 2
  • 24
  • 36
  • 1
    Thanks! So the operators for `floatn`and and such are only defined inside the kernel? And do you have an idea where my problem with `-std=c99` does come from? – TeaOverflow Jun 11 '12 at 13:47
2

cl_float.v is another option:

#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;
}

which can be run as:

gcc -std=c89 -Wall -Wextra tmp.c -lOpenCL && ./a.out 

in Ubuntu 16.10, gcc 6.2.0.

v is defined in Linux GCC x86 via GCC vector extensions.

The file https://github.com/KhronosGroup/OpenCL-Headers/blob/bf0f43b76f4556c3d5717f8ba8a01216b27f4af7/cl_platform.h contains:

#if defined( __SSE__ )
    [...]
    #if defined( __GNUC__ )
        typedef float __cl_float4   __attribute__((vector_size(16)));
    [...]
    #define __CL_FLOAT4__   1

and then:

typedef union
{
[...]
#if defined( __CL_FLOAT4__) 
    __cl_float4     v4;
#endif
}cl_float4;

Not sure this barrage of ifdefs was a good move by Khronos, but it is what we have.

I recommend that you just always use .s[0], which is the most portable option. We shouldn't need to speedup the host SIMD if we are focusing on the GPU...

C11 anonymous structs

The error error: ‘cl_float3’ has no member named ‘x’ happens because of the lines mentioned at: https://stackoverflow.com/a/10981639/895245

More precisely, this feature is called "anonymous struct", and it is an extension that was standardized in C11.

So in theory it should also work with -std=c11, but it currently doesn't because the CL headers weren't updated to check for C11, see also: https://github.com/KhronosGroup/OpenCL-Headers/issues/18

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985