2010-03-11 9 views
10

gmp 유형 (mpz_t, mpq_t, ...)과 같은 OpenCL 커널에서 사용자 정의 유형을 사용할 수 있습니까? 네 번째 매개 변수에 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]); 
} 

미정 :

는 다음과 같이 (이 커널 단지 때문에 #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

+1

@dietr "이 변수는 커널에 전달 될 예정이다"와 같이 코드 명료성에 도움이됩니다. – Thomas

4

나는 VHISTov의 답변과 다이어트를 통해 내 작업을 얻었습니다. 이 코드는 커널

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 ☺

,369

의 OpenCL 1.2에 나를 위해 작동

1 ☻

2 ♥

3 명 ♦

4 ♣

+5

왜 myStruct [gid] 대신에 (myStruct + gid) -> a = gid; gid; 그게 나를 위해 못 생겼어 (그러나, 같은 결과를 줄 것이다) – DarkZeros

관련 문제