Tipi personalizzati nel kernel OpenCL
Domanda
È possibile utilizzare tipi personalizzati nel kernel OpenCL come i tipi gmp (mpz_t, mpq_t, ...)?
Per avere qualcosa del genere (questo kernel non viene compilato solo a causa di #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]); }
Magari aggiungendo argomenti diversi al quarto parametro (opzioni) Di clBuildProgram
?
Oppure OpenCL ha già tipi che possono gestire grande numeri?
Soluzione
È possibile utilizzare i tipi personalizzati, ma nulla utilizzati nel kernel deve essere specificamente scritta per OpenCL. Dai un'occhiata a questo sito, forse per come implementare i numeri di precisione più grandi: FP128
Modifica:. Di NVIDIA CUDA SDK è un complesso tipo di numero di dati, non è l'ideale, ma può darvi alcune idee su come vanno circa esso, OpenCL dovrebbe essere simile
Altri suggerimenti
In genere è possibile utilizzare qualsiasi tipo in un programma OpenCL. Ma dal momento che le importazioni non funzionano, è necessario ri-definire all'interno dello stesso programma. Ad esempio:
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;
}
Tuttavia, è ovviamente necessario mantenere le definizioni all'interno e all'esterno OpenCL lo stesso. Assicurarsi inoltre che il tipo ha le stesse dimensioni su entrambi i dispositivi e host (utilizzando un sizeof(my_struct)
dovrebbe fare il trucco). In alcuni casi ho dovuto regolare le definizioni, per avere dimensioni corrispondenti.
Ho usato la risposta di VHristov e il commento di Dietr per far funzionare il mio.Questo codice funziona per me in OpenCL 1.2
nocciolo
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;
}
ospite
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;
}
produzione
0 ☺
1 ☻
2 ♥
3 ♦
4 ♣
Se si desidera includere nel file header file del kernel, è possibile aggiungere il -l dir come argomento per clBuildProgram, dove dir è la directory con i file header .
Più spiegazione qui: includono intestazioni a OpenCL file di .cl
Fonte: http: // www .khronos.org / registro / cl / sdk / 1.0 / docs / uomo / xhtml / clBuildProgram.html