سؤال

هل من الممكن استخدام أنواع مخصصة في OpenCL Kernel مثل أنواع GMP (MPZ_T، MPQ_T، ...)؟

أن يكون هناك شيء من هذا القبيل (هذا النواة لا يبني فقط بسبب #include <gmp.h>) :

#تضمنu003Cgmp.h> __kernel Square (__global MPZ_T * الإدخال، __global MPZ_T رقم، __global Int * الإخراج، CONS UNT INT CONT) {int i = get_global_id (0)؛ إذا (أنا <عد) الإخراج [i] = mpz_divisible_p (الرقم والإدخال [i])؛ }

ربما عن طريق إضافة حجج مختلفة إلى المعلمة الرابعة (والخيارات) من clBuildProgram ?

أو هل لدى OpenCL بالفعل أنواع يمكنها التعامل معها كبير أعداد ؟

هل كانت مفيدة؟

المحلول

يمكنك استخدام أنواع مخصصة ولكن أي شيء يستخدم في kernel يحتاج إلى مكتوب خصيصا لبرنامج OpenCL. تحقق من هذا الموقع ربما لكيفية تنفيذ أرقام دقة أكبر: FP128.

تحرير: يحتوي NVIDIA's CUDA SDK على نوع بيانات رقم معقد، إنه ليس مثاليا ولكنه قد يوفر لك بعض الأفكار حول كيفية استمراره، يجب أن يكون OpenCL مشابها.

نصائح أخرى

بشكل عام، يمكنك استخدام أي أنواع في برنامج 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) يجب أن تفعل الخدعة). في بعض الحالات، اضطررت إلى ضبط التعاريف، للحصول على أحجام مطابقة.

لقد استخدمت إجابة Vhristov وتعليق DITTR للحصول على عمل الألغام. هذا الرمز يعمل بالنسبة لي في 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 ♣

إذا كنت ترغب في تضمين ملفات الرأس في ملف Kernel، فيمكنك إضافة -l دير كحجة لضبط البرمجيات، حيث دير هو الدليل مع ملفات الرأس.

المزيد من التفسير هنا: تضمين رؤوس إلى ملف opencl .cl

مصدر: http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clbuildpram.html.html.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top