为什么程序(全局)范围变量必须是__constant?

Aea*_*ean 6 global-variables opencl

我是OpenCL的新手,并且对此限制感到困惑.例如,如果我想写一个LCG,我必须使状态字可以修改为rand()srand().在ANSI C中,我将使用以下内容执行此操作:

/* ANSI C */
static unsigned long _holdrand = 1; /* Global! */

unsigned long rand(){
    _holdrand = _holdrand * 214013L + 2531011L;
    return (_holdrand >> 16) & 0x7FFF; 
}
void srand( unsigned long seed ){
    _holdrand = seed;
}
Run Code Online (Sandbox Code Playgroud)

但OpenCL限制所有全局范围变量__constant.我可以_holdrand进入函数范围,并将其指针退出该函数.

/* OpenCL C */
uint* holdrand(){
    __private static uint _holdrand = 1;
    return &_holdrand;
}

uint rand(){
    *holdrand() = *holdrand() * 214013L + 2531011L;
    return (*holdrand() >> 16) & 0x7FFF; 
}
void srand( uint seed ){
    *holdrand() = seed;
}
Run Code Online (Sandbox Code Playgroud)

它工作正常,我不知道这是否是一个很好的解决方案.这个限制是胡说八道,我只是通过添加更多奇怪的代码来避免它.

__private uint _holdrand = 1;
/* It should be the same thing... Why this is not allowed? */
Run Code Online (Sandbox Code Playgroud)

由于返回静态指针方式的行为与ANSI C中的全局范围变量方法完全相同,我无法理解限制含义.有人能解释为什么吗?我错过了什么吗?_holdrand在本例中,如何在两个不同的函数中进行修改?

Rom*_*yan 4

简而言之 - OpenCL 程序生命周期和内存布局与 C 程序不同。在 OpenCL 中,没有堆栈、堆等。常量内存(通常)非常快且片上内存量很少,与寄存器操作相比,IO 操作具有相同的性能顺序。因此,它对工作项的写入操作可能有限制。

每个 NDRange(通常)中都有数千个工作项 (WI)。想象一下,如果 512 个线程正在读取/写入同一个变量,您可以实现什么性能。这就是为什么你有 4 个地址空间:

  • __private对于每一个WI
  • __local对于工作组内的所有 WI
  • __global适用于 NDRange 内的所有 WI
  • __constant对于全局只读变量

如果你的rand()srand()函数是 WI 特定的,您应该使用私有内存。另一种方法是在全局地址空间中包含所需的变量。但在这种情况下要非常小心竞争条件。

OpenCL 可以在各种各样的设备上运行,这就是为什么某些限制看起来太严格的原因。