0

I'm trying to run a basic kernel in OpenCL. See the snipped attached

const char kernel_source[] = "__kernel void matmul(__global float* A, __global float* B, __global float* C) { int row = get_global_id(0); int col = get_global_id(1); int N = get_global_size(0); int idx = (row * N) + col; for (int i = 0; i < N; i++) { C[idx] += A[row * N + i] * B[i * N + col]; } }";

void check_error(cl_int err, char step[]);
int check_result(float mat_a[NUM_ROWS][NUM_COLS], float mat_b[NUM_ROWS][NUM_COLS], float mat_c[NUM_ROWS][NUM_COLS]);

int main()
{
    // Set up platform, device and context
    cl_int CL_err = CL_SUCCESS;

    cl_platform_id platform;

    CL_err = clGetPlatformIDs(1, &platform, NULL);
    check_error(CL_err, "Couldn't find platform");

    cl_device_id device;
    CL_err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
    check_error(CL_err, "Couldn't find device");


    cl_context context = clCreateContext(NULL, 1, &device, NULL, NULL, &CL_err);
    check_error(CL_err, "Couldn't create context");

    cl_command_queue command_queue = clCreateCommandQueue(context, device, 0, &CL_err);
    check_error(CL_err, "Couldn't create command queue");

    cl_program program = clCreateProgramWithSource(context, 1, (const char**)&kernel_source, NULL, &CL_err);
    check_error(CL_err, "Couldn't create the program");

As it is, I get a read access violation on clCreateProgramWithSource. I tried removing the const qualifier and moving the string declaration into function scope but got the same issue either way. String literals are guaranteed to be null terminated by C, but I also did try passing in the length explicitly.

However, I switched to C++ and used the cl::Program constructor to build the kernel and the kernel compiled without issue. Later, in the same C program, I dynamically allocated the same string like so

int length = strlen(kernel_source);
char* temp = malloc(length + 1);
if (temp == NULL) {
    return -1;
}
memcpy(temp, kernel_source, length + 1);

I passed in a pointer to the dynamically allocated string instead and this also fixed the issue. Note that with the C++ wrapper, the actual call to clCreateProgramWithSource has the same arguments that my C code does, but with a new copy of the string - since the string is converted to an std::string and then back to a C-string.

Does Visual Studio treat strings differenly than other compilers and make it somehow inaccessible to OpenCL? I've seen many examples online of kernel source code being passed in the same way.

3
  • Is the answer you got acceptable? Did it solve the issue for you? Commented Jun 18 at 18:21
  • It was thank you! Guess I just forgot the basic workings of C. Commented Jun 19 at 23:46
  • It was however not my answer :-) You can accept answers you get by clicking the checkmark beside the answer you like the best. Commented Jun 19 at 23:50

1 Answer 1

2
const char kernel_source[] = "...";
clCreateProgramWithSource(context, 1, (const char**)&kernel_source, ...);

You are lying to your compiler. kernel_source is an array, but the function expects an address of a pointer. An array is not a pointer. An address of an array is not the same thing as an address of a pointer. These two things are totally different and incompatible.

What you need is

const char* kernel_source = "...";
clCreateProgramWithSource(context, 1, &kernel_source, 1, ...);

Note, kernel_source is a pointer. You are passing an address of a pointer, which the function expects. No casts, no errors.

Sign up to request clarification or add additional context in comments.

1 Comment

An alternative could be to split the kernel source on several lines example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.