【问题标题】:__local struct array opencl__local 结构数组 opencl
【发布时间】:2014-12-06 09:56:52
【问题描述】:

我对这行代码有一些问题:

__local cl_var new_vars[10];

这些都有效:

__local cl_var test;
__local int test[10];
__local cl_var * test

供参考,cl_var 是:

typedef struct cl_var{
   int var;
   struct cl_var* next;
} cl_var;

尝试编译时出现段错误。我使用的是 JOCL 包,不确定这是否会有所不同。

为什么我不能在本地声明一个结构数组?

(我已尝试更改结构定义以在各个地方包含本地)

【问题讨论】:

  • 我认为您不能包含指向自身的指针。因为它还没有定义。此外,它还会产生无限递归问题。
  • @DarkZeros 我最初确实遇到了这个问题,但包括 struct 关键字修复了这个问题,我猜它是一个不同的命名空间。此外,它在任何地方都可以使用,除非将其用作本地数组。
  • @ParkYoung-Bae 这是正确的 - 很奇怪吧?

标签: arrays struct opencl


【解决方案1】:

原因是内存对齐。根据这个article和其中的cmets,你必须小心对齐。本页评论部分对 David Garcia 的解释非常清楚对齐:一些编译器可能会选择将结构大小填充到 16 个字节。

post in Khronos forum 中有重要的附加信息:

OpenCL 中的基本数据类型(整数和浮点数据类型)具有定义的大小和对齐要求(请参阅 OpenCL 1.1 规范的第 6.1.5 节)。为了确保在设备上使用这些数据类型的主机和 OpenCL 内核之间的对齐匹配,请使用 cl_ 来声明将由主机和设备共享的结构(请参阅 1.1 规范中表 6.1 之后的表格)。

所以你应该使用cl_float而不是float,如果我理解spec page on basic OpenCL types,也许还可以明确指定对齐方式:

对于三分量向量数据类型,数据类型的大小为 4 * sizeof(component)。这意味着 3 分量矢量数据类型将与 4 * sizeof(component) 边界对齐。

所以也许显式对齐会解决你的问题。

除此之外,这个答案的第二部分:

请注意,这仅适用于整数和浮点数据类型。对齐规则不适用于指针。这就是为什么指针不能嵌入到 OpenCL 结构中的原因之一。

OpenCL 规范在这个主题上非常清楚:“你不能将包含指针的结构传递给 OpenCL”(引自 here,并确认了 there,我懒得抓规范页面。 .. :) )。显然这里不是这种情况,但是您的结构不会是内核参数的有效类型。

【讨论】:

  • 我没有将它传递给内核参数,这些都是在函数中声明的,而且 - 它导致问题的唯一时间是在本地数组中使用时,当以任何其他方式使用时描述它有效。
  • 是的,这就是为什么 struct 事物中的指针并不真正相关的原因,但我认为值得一提。但是您是否尝试过声明结构的 16 字节对齐方式?
  • 我没有,我现在会考虑这样做,但为什么这只影响本地数组,而不影响任何其他类型的数组、本地指针或本地法线?
  • 如果我的假设是正确的,那么问题是它是一个静态数组,如果编译器假定为 4 字节对齐,则大小不匹配。指针没有这个问题,因为您没有指定大小。单个变量的同上。但这是一个想法......
  • 有意思,我去看看。谢谢
【解决方案2】:

我无法在编译时(甚至在运行时)重现错误。我不熟悉 JOCL,所以在那个方向上无能为力。 我正在为 OpenCL 内核使用 Windows、NVIDIA 和 JIT 编译。

您是否还通过访问new_vars 来使用内核中分配的内存,还是仅声明__local cl_var new_vars[10]; 并发生错误?

“我已尝试更改结构定义以在各个地方包含本地”是什么意思?您是否已将local 地址空间限定符添加到“下一个”指针? 如果是这样,那么我的以下解释可能不是解决方案。

据我所知,该错误的潜在原因是缺少地址空间限定符(无法验证,因为我无法重现该错误)。您的问题是 OpenCL 中的指针类型总是带有地址空间限定符 privatelocalglobalconstant(参见 here)。如果你忽略它,OpenCL 默认选择私有:“如果没有指定地址空间限定符,声明为指针的变量被认为指向 __private 地址空间”(参见Notes)。

这就是你的结构发生的事情。在结构体中,您声明了一个指向结构体本身的指针,但是您没有指定任何地址空间限定符,因此默认设置为私有。

写作

typedef struct cl_var{
   int var;
   struct cl_var* next;
} cl_var;

相当于写

typedef struct cl_var{
   int var;
   private struct cl_var* next;
} cl_var;

当通过写入__local cl_var new_vars[10]; 在本地内存中静态分配 10 个 cl_var 对象时,地址空间限定符不匹配,因为对象驻留在本地内存中,但期望指向私有内存中的对象(“下一个”)。所以当在对象中使用指针时,你的程序应该会崩溃,但只是在运行时,而不是编译时(除非你的编译器非常敏感——在这种情况下这实际上是一件好事)。

通过写作

typedef struct cl_var{
   int var;
   local struct cl_var* next;
} cl_var;

你应该能够分配内存。

旁注:尽量不要用“new”来命名你的数组,因为它与动态内存分配的关系可能会让人们感到困惑(并且动态内存分配不是你的示例代码中发生的事情!)。

【讨论】:

    猜你喜欢
    • 2013-02-21
    • 2012-02-29
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多