我是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? */
由于返回静态指针方式的行为与ANSI C中的全局范围变量方法完全相同,我无法理解限制含义。有人能解释为什么吗?我错过了什么吗?在本例中,如何使_holdrand
在两个不同的函数中可修改?
答案 0 :(得分:4)
简要介绍 - OpenCL程序生命周期&内存布局与C程序不同。在OpenCL中,你没有堆栈,堆等。恒定的内存(通常)非常快&与寄存器操作相比,少量的片上存储器,IO操作具有相同的性能顺序。因此,它可能对工作项的写操作有限制。
在每个NDRange(通常)中都有数千个工作项(WI)。想象一下,如果512个线程正在读/写同一个变量,那么你可以达到什么样的性能。这就是为什么你有4个地址空间的原因:
__private
__local
__global
适用于NDRange中的所有WI __constant
表示全局只读变量如果你的rand()
& srand()
函数是特定于WI的,您应该使用私有内存。另一种方法是在全局地址空间中包含所需的变量。但在这种情况下要非常小心竞争条件。
OpenCL可以在各种各样的设备上运行,这就是为什么某些限制看起来太强大了。