Pergunta

É possível usar tipos personalizados no kernel do OpenCL como tipos BPF (mpz_t, mpq_t, ...)?

Para ter algo como isto (este kernel não constrói apenas por causa de #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]);
}

Talvez adicionando argumentos diferentes para o quarto parâmetro ( Opções ) de clBuildProgram?

Ou OpenCL já tem tipos que podem lidar com grande números?

Foi útil?

Solução

Você pode usar tipos personalizados, mas nada utilizados nas necessidades do kernel a ser escritos especificamente para OpenCL. Confira este site talvez para como implementar números de precisão maiores: FP128

Edit: NVIDIA CUDA SDK tem um tipo de dados número complexo, não é o ideal, mas pode lhe dar algumas idéias sobre como eles poderiam fazer isto, OpenCL deve ser semelhante

.

Outras dicas

Geralmente você pode usar qualquer tipo de um programa OpenCL. Mas desde que as importações não fazer o trabalho, você tem que re-defini-los dentro do mesmo programa. Por exemplo:

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

No entanto, você obviamente precisa manter as definições dentro e fora OpenCL o mesmo. Também certifique-se o tipo tem o mesmo tamanho em ambos dispositivo e host (usando um sizeof(my_struct) deve fazer o truque). Em alguns casos eu tive que ajustar as definições, para ter tamanhos correspondentes.

Eu usei a resposta de VHristov e comentário de Dietr pegar o meu trabalho. Esse código funciona para mim em OpenCL 1.2

do kernel

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

hospedeiro

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

saída

0 ?

1 ?

2 ?

3 ?

4 ?

Se você quiser incluir arquivos de cabeçalho no arquivo do kernel, você pode adicionar o -l dir como um argumento para clBuildProgram, onde dir é o diretório com os arquivos de cabeçalho .

Mais explicações aqui: incluir cabeçalhos de arquivo OpenCL .cl

Fonte: http: // www .khronos.org / registro / cl / SDK / 1,0 / docs / homem / XHTML / clBuildProgram.html

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top