2010-03-11 164 views
10

是否可以在OpenCL内核中使用类似于gmp类型(mpz_t,mpq_t,...)的自定义类型?通过添加不同的参数来第四个参数的clBuildProgram选项OpenCL内核中的自定义类型

 
#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]); 
} 

可能:

为有这样的事情(kernel没有建立的,只是因为#include <gmp.h>)?

还是OpenCL已经有类型可以处理数字?

回答

4

您可以使用自定义类型,但内核中使用的任何内容都需要专门为OpenCL编写。看看这个网站可能是关于如何实现更大精度的数字:FP128

编辑:NVIDIA的CUDA SDK有一个复杂的数字数据类型,它不是理想的,但可能会给你一些关于它如何去做的想法,OpenCL应该是相似的。

18

通常,您可以在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)应该可以做到这一点)。在某些情况下,我必须调整定义,以匹配大小。

+4

为了确保同样大小的类型,这是一个好主意,在主机代码(cl_int,cl_long,cl_float2等)使用CL_ *类型。 – dietr 2010-09-20 06:21:59

+1

@dietr它也有助于代码的清晰度,因为“这个变量是为了传递给内核” – Thomas 2013-11-23 01:27:35

4

我用VHristov的回答和dietr的评论来得到我的工作。此代码对我的作品中的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♣

+5

为什么使用'(myStruct + gid) - > a = gid;'而不是'myStruct [gid] .a = GID;'。这对我来说看起来很丑(但是,会得到相同的结果) – DarkZeros 2013-09-24 10:00:18