OpenCL 内核中的自定义类型

发布于 2024-08-25 05:55:06 字数 496 浏览 3 评论 0原文

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

要拥有这样的东西(这个内核不只是因为#include而构建):

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

也许通过向第四个参数添加不同的参数(选项 ) 的 clBuildProgram ?

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

Is it possible to use custom types in OpenCL kernel like gmp types (mpz_t, mpq_t, …) ?

To have something like this (this kernel doesn't build just because of #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]);
}

Maybe by adding different arguments to the fourth parameter (options) of clBuildProgram ?

Or does OpenCL already have types that can handle large numbers ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

云胡 2024-09-01 05:55:06

一般来说,您可以在 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) 应该可以解决问题)。在某些情况下,我必须调整定义,以获得匹配的大小。

Generally you can use any types in an OpenCL program. But since imports do not work, you have to re-define them within the same program. For example:

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

However, you obviously need to keep the definitions within and outside OpenCL the same. Also make sure the type has the same size on both device and host (using a sizeof(my_struct) should do the trick). In some cases I had to adjust the definitions, to have matching sizes.

忆伤 2024-09-01 05:55:06

我使用 VHristov 的答案和 Dietr 的评论来让我的工作正常进行。此代码适用于 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;
}

host

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

output

0 ☺

1 ☻

2 ♥

3 ♦

4 ♣

I used VHristov's answer and dietr's comment to get mine working. This code works for me in 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;
}

host

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

output

0 ☺

1 ☻

2 ♥

3 ♦

4 ♣

寂寞陪衬 2024-09-01 05:55:06

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

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

You can use custom types but anything used in the kernel needs to be specifically written for OpenCL. Check out this website perhaps for how to implement larger precision numbers: FP128

Edit: NVIDIA's CUDA SDK has a complex number data type, it's not ideal but may give you some ideas on how they go about it, OpenCL should be similar.

岁月流歌 2024-09-01 05:55:06

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

更多说明请参见:将标头包含到 OpenCL .cl 文件

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

If you want to include header files into kernel file, you can add the -l dir as an argument to clBuildProgram, where dir is the directory with the header files.

More explanation here: include headers to OpenCL .cl file

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文