2010-03-11 11 views
10

Có thể sử dụng các loại tùy chỉnh trong hạt nhân OpenCL như các loại gmp (mpz_t, mpq_t,…) không?Các loại tùy chỉnh trong hạt nhân OpenCL

Để có một cái gì đó như thế này (kernel này không xây dựng chỉ vì #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]); 
} 

Có lẽ bằng cách thêm tham số khác nhau để tham số thứ tư (tùy chọn) của clBuildProgram?

Hoặc OpenCL đã có các loại có thể xử lý số lớn?

Trả lời

4

Bạn có thể sử dụng các loại tùy chỉnh nhưng mọi thứ được sử dụng trong hạt nhân cần được ghi riêng cho OpenCL. Kiểm tra trang web này có lẽ để biết cách triển khai các con số chính xác lớn hơn: FP128

Chỉnh sửa: CUDA SDK của NVIDIA có kiểu dữ liệu số phức tạp, không lý tưởng nhưng có thể cung cấp cho bạn một số ý tưởng về cách thực hiện, OpenCL .

18

Thông thường, bạn có thể sử dụng bất kỳ loại nào trong chương trình OpenCL. Nhưng kể từ khi nhập khẩu không hoạt động, bạn phải xác định lại chúng trong cùng một chương trình. Ví dụ:

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

Tuy nhiên, bạn rõ ràng cần giữ các định nghĩa trong và ngoài OpenCL giống nhau. Ngoài ra, hãy đảm bảo loại có cùng kích thước trên cả thiết bị và máy chủ (sử dụng số sizeof(my_struct) nên thực hiện thủ thuật). Trong một số trường hợp, tôi phải điều chỉnh các định nghĩa để có kích thước phù hợp.

+4

Để đảm bảo loại kích thước bằng nhau, đó là một ý tưởng tốt để sử dụng cl_ * loại trong mã máy chủ (cl_int, cl_long, cl_float2, vv). – dietr

+1

@dietr Nó cũng giúp mã rõ ràng, như trong "biến này có nghĩa là để được chuyển cho một hạt nhân" – Thomas

4

Tôi đã sử dụng câu trả lời của VHristov và bình luận của chế độ ăn uống để giúp tôi làm việc. Mã này làm việc cho tôi trong OpenCL 1.2

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

chủ

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

đầu ra

0 ☺

1 ☻

2 ♥

3 ♦

4 ♣

+5

Tại sao sử dụng '(myStruct + gid) -> a = gid;' thay vì 'myStruct [gid] .a = gid; '. Điều đó có vẻ xấu xí đối với tôi (tuy nhiên, sẽ cho kết quả tương tự) – DarkZeros