我是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;
}
但是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;
}
它工作得很好,我不知道这是否是一个好的解决方案。这个限制毫无意义,我只是通过添加更多奇怪的代码来避免它。
__private uint _holdrand = 1;
/* It should be the same thing... Why this is not allowed? */
由于return-a-pointer-of-static方式的行为与ANSI C中的全局作用域变量方法完全相同,因此我无法理解该限制的含义。有人能解释一下原因吗?我错过什么了吗?在这个例子中,我应该怎么做才能使_holdrand
在两个不同的函数中可修改?
简要说明- OpenCL程序生命周期&内存布局不同于C程序。在OpenCL中,你没有堆栈,堆等。恒速存储器(通常)非常快。少量的片上存储器,与寄存器操作相比,IO操作具有相同的性能顺序。因此,它可能对来自工作项的写操作有限制。
在每个nrange中(通常)有数千个工作项(WI)。想象一下,如果有512个线程正在读写相同的变量,您可以达到什么样的性能。这就是为什么你有4个地址空间:
-
__private
每个WI -
__local
用于工作组内所有wi - nrange内所有WI
__global
-
__constant
用于全局只读变量
如果你的rand()
&srand()
函数是特定于wi的,您应该使用私有内存。另一种方法是在全局地址空间中使用所需的变量。但是在这种情况下,要非常小心使用竞态条件。
OpenCL可以在各种各样的设备上运行,这就是为什么有些限制看起来太强了。