Пользовательские типы в ядре OpenCL
Вопрос
Можно ли использовать пользовательские типы в ядре 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]); }
Возможно, путем добавления различных аргументов к четвертому параметру (Опции) из clBuildProgram
?
Или в OpenCL уже есть типы, которые могут обрабатывать Большой цифры ?
Решение
Вы можете использовать пользовательские типы, но все, что используется в ядре, должно быть специально написано для OpenCL.Возможно, ознакомьтесь с этим веб-сайтом, чтобы узнать, как реализовать числа большей точности: ФП128
Редактировать:CUDA SDK от NVIDIA имеет тип данных complex number, он не идеален, но может дать вам некоторые идеи о том, как они это делают, OpenCL должен быть похожим.
Другие советы
Как правило, вы можете использовать любые типы в программе 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)
должно сработать).В некоторых случаях мне приходилось корректировать определения, чтобы иметь соответствующие размеры.
Я использовал ответ Христова и комментарий дитра, чтобы заставить мой работать.Этот код работает для меня в 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 ♣
Если вы хотите включить заголовочные файлы в файл ядра, вы можете добавить -l реж в качестве аргумента clBuildProgram, где реж это каталог с заголовочными файлами.
Более подробное объяснение здесь: включить заголовки в файл OpenCL .cl
Источник: http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clBuildProgram.html