Пользовательские типы в ядре OpenCL - PullRequest
11 голосов
/ 11 марта 2010

Можно ли использовать в ядре OpenCL пользовательские типы, такие как типы gmp (mpz_t, mpq_t,…)?

Чтобы получить что-то подобное (это ядро ​​не собирается только из-за #include <gmp.h>):

#include <gmp.h>
__kernel square(
   __global mpz_t* input,
   __global mpz_t number,
   __global int* output,
   const unsigned int count)
{
   int i = get_global_id(0);
   if(i < count)
       output[i] = mpz_divisible_p(number,input[i]);
}

Может быть, добавив различные аргументы к четвертому параметру ( options ) clBuildProgram?

Или OpenCL уже имеет типы, которые могут обрабатывать большие цифры?

Ответы [ 4 ]

21 голосов
/ 22 июля 2010

Как правило, вы можете использовать любые типы в программе OpenCL. Но так как импорт не работает, вы должны переопределить их в рамках одной и той же программы. Например:

typedef char my_char[8];

typedef struct tag_my_struct
{
    long int        id;
    my_char         chars[2];
    int             numerics[4]
    float           decimals[4];
} my_struct;

__kernel void foo(__global my_struct * input,
                  __global int * output)
{
    int gid = get_global_id(0);
    output[gid] = input[gid].numerics[3]== 2 ? 1 : 0;
}

Однако вам, очевидно, нужно сохранять определения внутри и вне OpenCL одинаковыми. Также убедитесь, что тип имеет одинаковый размер как на устройстве, так и на хосте (использование sizeof(my_struct) должно помочь). В некоторых случаях мне приходилось корректировать определения, чтобы они соответствовали размерам.

7 голосов
/ 24 августа 2013

Я использовал ответ В.Христова и диетолога, чтобы заставить мою работать Этот код работает для меня в OpenCL 1.2

ядро ​​

typedef struct tag_my_struct{
  int a;
  char b;
}my_struct;

__kernel void myKernel(__global my_struct *myStruct)
{
    int gid = get_global_id(0);
    (myStruct+gid)->a = gid;
    (myStruct+gid)->b = gid + 1;
}

хозяин

typedef struct tag_my_struct{
  cl_int a;
  cl_char b;
}my_struct;

void runCode() 
{
    cl_int status = 0;
    my_struct* ms = new my_struct[5];

    cl_mem mem = clCreateBuffer(*context, 0, sizeof(my_struct)*5, NULL, &status);
    clEnqueueWriteBuffer(*queue, mem, CL_TRUE, 0, sizeof(my_struct)*5, &ms, 0, NULL, NULL);

    status = clSetKernelArg(*kernel, 0, sizeof(ms), &mem);

    size_t global[] = {5};
    status = clEnqueueNDRangeKernel(*queue, *kernel, 1, NULL, global, NULL, 0, NULL, NULL);

    status = clEnqueueReadBuffer(*queue, mem, CL_TRUE, 0, sizeof(my_struct)*5, ms, 0, NULL, NULL);

    for(int i = 0; i < 5; i++)
        cout << (ms+i)->a << " " << (ms+i)->b << endl;
}

выход

0 ☺

1 ☻

2 ♥

3 ♦

4 ♣

4 голосов
/ 14 марта 2010

Вы можете использовать пользовательские типы, но все, что используется в ядре, должно быть специально написано для OpenCL. Посетите этот веб-сайт, чтобы узнать, как реализовать большие числа точности: FP128

Редактировать: NVIDIA CUDA SDK имеет тип данных комплексного числа, он не идеален, но может дать вам некоторые идеи о том, как они это делают, OpenCL должен быть похожим.

3 голосов
/ 24 сентября 2013

Если вы хотите включить заголовочные файлы в файл ядра, вы можете добавить -l dir в качестве аргумента clBuildProgram, где dir - это каталог с заголовочными файлами.

Более подробное объяснение здесь: включает заголовки в файл OpenCL .cl

Источник: http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clBuildProgram.html

...