持续的:所有工作人员都可以看到缓存的全局内存的一小部分。如果可以的话使用它,只读。
Global:缓慢,所有人都可以看到,读或写。这是所有数据都将结束的地方,因此始终需要对其进行一些访问。
Local:您需要在本地群组中分享一些内容吗?使用本地!您的所有本地工作人员是否都访问相同的全局内存?使用本地!
本地内存仅在本地工作人员内部可见,并且大小有限,但速度非常快。
Private:仅对工作人员可见的内存,将其视为寄存器。默认情况下,所有未定义的值都是私有的。
假设我将一个类型为 long 且长度为 10000 的数组传递给内核,我
只会用于读取,那么我将声明它为全局常量,因为它必须
可供所有工人使用,并且不会改变。我为什么不使用
常量限定符?
事实上,是的,你可以而且应该使用constant
预选赛。它将您的数据放置在常量内存中(所有工作人员都可以快速访问的一小部分只读内存)。 GPU 使用它来将统一传输到所有顶点着色器。
当通过CPU为这个数组设置缓冲区时,我实际上也
只是可以使数组只读,在我看来,
与声明它为 const 相同。再说一次,我何时以及为什么要宣布
常量或全局常量?
事实并非如此,当您创建只读缓冲区时,您仅指定 OpenCL 您计划以只读方式使用它,因此它可以在后面进行优化,但您实际上可以从内核写入它。global const
只是开发者的一个保障,所以你不小心写入它,它就会在编译时给出错误。
基本上与纯 C 主机端计算相同。如果所有内存都是非常量的,程序也能正常工作。
当执行内存密集型任务时,将数组复制到内核内部的本地数组会更好吗?我的猜测是本地内存太小了,但是如果数组的长度只有 10 怎么办?数组什么时候会太大/太小?更一般地说:什么时候值得将数据从全局内存复制到本地内存?
只有所有工人都阅读它才有价值。如果每个worker读取全局内存的单个值,那么这是不值得的。
这里有用:
Worker0 -> Reads 0,1,2,3
Worker1 -> Reads 0,1,2,3
Worker2 -> Reads 0,1,2,3
Worker3 -> Reads 0,1,2,3
在这里没用:
Worker0 -> Reads 0
Worker1 -> Reads 1
Worker2 -> Reads 2
Worker3 -> Reads 3
假设我还想传递这个数组的长度,那么我会添加
const int length 到我的内核参数,但我不确定为什么我
会省略全局限定符,除非我见过其他的
人们这样做。毕竟,长度必须对所有工人来说都是可访问的。如果
我是对的,那么 length 将有一个通用的地址空间,但同样,
我真的不知道这意味着什么。
当您未在内核参数中指定限定符时,它通常默认为constant
,这就是您希望这些小元素能够被所有工作人员快速访问。
OpenCL 编译器通常遵循的内核参数规则是:如果它只读取并适合常量,则常量,否则全局。