【问题标题】:Custom types in OpenCL kernelOpenCL 内核中的自定义类型
【发布时间】:2011-01-26 07:11:55
【问题描述】:

是否可以在 OpenCL 内核中使用自定义类型,例如 gmp 类型(mpz_t、mpq_t、...)?

拥有这样的东西(这个内核不会仅仅因为#include <gmp.h>而构建):

#include __内核正方形( __global mpz_t* 输入, __global mpz_t 编号, __global int* 输出, const unsigned int 计数) { int i = get_global_id(0); 如果(我

也许通过在clBuildProgram 的第四个参数(options)中添加不同的参数?

或者 OpenCL 是否已经有可以处理 large 数字的类型?

【问题讨论】:

    标签: types opencl gmp


    【解决方案1】:

    通常您可以在 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) 应该可以解决问题)。在某些情况下,我不得不调整定义以匹配大小。

    【讨论】:

    • 为确保类型大小相等,最好在主机代码中使用 cl_* 类型(cl_int、cl_long、cl_float2 等)。
    • @dietr 它还有助于代码清晰,如“此变量旨在传递给内核”
    【解决方案2】:

    我使用 VHristov 的回答和节食者的评论来让我的工作。此代码在 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 ♣

    【讨论】:

    • 为什么使用(myStruct+gid)-&gt;a = gid; 而不是myStruct[gid].a = gid;。这对我来说看起来很丑(但是,会产生相同的结果)
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      如果要将头文件包含到内核文件中,可以将-l dir作为参数添加到clBuildProgram,其中dir是包含头文件的目录.

      更多解释在这里:include headers to OpenCL .cl file

      来源:http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clBuildProgram.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-06
        • 2015-10-23
        相关资源
        最近更新 更多