OpenCL 何时使用全局、私有、本地、常量地址空间
OpenCL When to use global, private, local, constant address spaces
我正在尝试学习 OpenCL,但我很难决定使用哪个地址 space,因为我只找到 assembled 资源声明这些地址 spaces 是,但不是它们存在的原因或何时使用它们。至少资源太分散了,所以带着这个问题我希望assemble所有这些信息:所有地址space是什么,它们为什么存在,什么时候使用哪个地址 space 以及内存和性能方面的优缺点。
据我了解(这可能过于简化),GPU 有两种物理内存类型:全局内存,与实际的处理器相去甚远,速度很慢但相当大所有工作人员都可以使用,本地内存,接近实际处理器,速度快但体积小,其他工作人员无法访问。
直觉上,local
限定符确保将变量放置在本地内存中,而 global
限定符确保将变量放置在全局内存中,但我不确定这是否准确发生什么了。这留下了 private
和 constant
限定符。这些的目的是什么?
还有一些隐含的限定词。例如,the specifications 提到 通用地址 space,我认为它用于没有限定符的参数。这到底是做什么的?然后还有局部函数变量。这些地址 space 是什么?
这是一个使用我的直觉的例子,但不知道我实际上在做什么:
示例:
假设我将类型为 long
且长度为 10000 的数组传递给一个我将仅用于读取的内核,然后我将声明它 global const
因为它必须对所有工作人员可用并且它不会改变。为什么我不使用 constant
限定符?当通过 CPU 为这个数组设置缓冲区时,我实际上也可以将数组设为只读,在我看来这与声明它 const
一样。再说一遍,我什么时候以及为什么要声明某些东西 constant
或 global const
?
在执行内存密集型任务时,将数组复制到内核内部的本地数组会更好吗?我的猜测是本地内存太小,但如果数组的长度只有 10 怎么办?数组什么时候会太big/small?更一般化:什么时候值得将数据从全局内存复制到本地内存?
假设我还想传递这个数组的长度,那么我会在内核的参数中添加 const int length
,但我不确定为什么我会省略 global
限定符,除了因为我见过其他人这样做。毕竟,所有工作人员都必须可以访问 length
。如果我是对的,那么 length
会有一个通用地址 space,但同样,我真的不知道那是什么意思。
希望有经验的大神指点一下。这不仅对我有好处,而且我希望对其他想要获得有关 GPU 内存管理的实用知识的爱好者也有帮助。
常量:一小部分缓存的全局内存对所有工作人员可见。如果可以就用它,只读。
全局:慢,所有人可见,读或写。这是您所有数据的结束位置,因此始终需要对其进行一些访问。
本地:您需要在本地群组中分享内容吗?使用本地!您所有的本地工作人员都访问相同的全局内存吗?使用本地!
本地内存仅在本地工作人员内部可见,并且大小有限,但速度非常快。
Private: 只对工作人员可见的内存,将其视为寄存器。默认情况下,所有未定义的值都是私有的。
Say I pass an array of type long and length 10000 to a kernel which I
will only use to read, then I would declare it global const as it must
be available to all workers and it will not change. Why wouldn't I use
the constant qualifier?
实际上,是的,您可以而且应该使用 constant
限定符。它将您的数据放在常量内存中(所有工作人员都可以快速访问的一小部分只读内存)。 GPU 使用它来将制服传输到所有顶点着色器。
When setting the buffer for this array via the CPU, I actually also
just could have made the array read-only, which in my eyes says the
same as declaring it const. So again, when and why would I declare
something constant or global const?
不是真的,当您创建一个只读缓冲区时,您只是向 OpenCL 指定您计划以只读方式使用它,因此它可以在后面进行优化,但您实际上可以从内核写入它。
global const
只是给开发者的一个保障,别不小心写进去了,编译的时候会报错。
基本上,与普通 C 主机端计算相同。如果所有内存都是非常量,程序也能正常工作。
When performing memory-intensive tasks, would it be better to copy the array to a local array inside the kernel? My guess is that local memory would be too small, but what if the array only had a length of 10? When would the array be too big/small? More general: when is it worth copying data from global to local memory?
只有所有工人都读过才有价值。如果每个 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
Say I also want to pass the length of this array, then I would add
const int length to the arguments of my kernel, but I'm unsure why I
would omit the global qualifier except because I have seen other
people do it. After all, length must be accessible for all workers. If
I'm right, then length would have a generic address space, but again,
I don't really know what that means.
当您没有在内核参数中指定限定符时,它通常默认为 constant
,这是您希望这些小元素能够被所有工作人员快速访问的。
OpenCL 编译器通常遵循的内核参数规则是:如果它仅读取并适合常量,则为常量,否则为全局。
我正在尝试学习 OpenCL,但我很难决定使用哪个地址 space,因为我只找到 assembled 资源声明这些地址 spaces 是,但不是它们存在的原因或何时使用它们。至少资源太分散了,所以带着这个问题我希望assemble所有这些信息:所有地址space是什么,它们为什么存在,什么时候使用哪个地址 space 以及内存和性能方面的优缺点。
据我了解(这可能过于简化),GPU 有两种物理内存类型:全局内存,与实际的处理器相去甚远,速度很慢但相当大所有工作人员都可以使用,本地内存,接近实际处理器,速度快但体积小,其他工作人员无法访问。
直觉上,local
限定符确保将变量放置在本地内存中,而 global
限定符确保将变量放置在全局内存中,但我不确定这是否准确发生什么了。这留下了 private
和 constant
限定符。这些的目的是什么?
还有一些隐含的限定词。例如,the specifications 提到 通用地址 space,我认为它用于没有限定符的参数。这到底是做什么的?然后还有局部函数变量。这些地址 space 是什么?
这是一个使用我的直觉的例子,但不知道我实际上在做什么:
示例:
假设我将类型为 long
且长度为 10000 的数组传递给一个我将仅用于读取的内核,然后我将声明它 global const
因为它必须对所有工作人员可用并且它不会改变。为什么我不使用 constant
限定符?当通过 CPU 为这个数组设置缓冲区时,我实际上也可以将数组设为只读,在我看来这与声明它 const
一样。再说一遍,我什么时候以及为什么要声明某些东西 constant
或 global const
?
在执行内存密集型任务时,将数组复制到内核内部的本地数组会更好吗?我的猜测是本地内存太小,但如果数组的长度只有 10 怎么办?数组什么时候会太big/small?更一般化:什么时候值得将数据从全局内存复制到本地内存?
假设我还想传递这个数组的长度,那么我会在内核的参数中添加 const int length
,但我不确定为什么我会省略 global
限定符,除了因为我见过其他人这样做。毕竟,所有工作人员都必须可以访问 length
。如果我是对的,那么 length
会有一个通用地址 space,但同样,我真的不知道那是什么意思。
希望有经验的大神指点一下。这不仅对我有好处,而且我希望对其他想要获得有关 GPU 内存管理的实用知识的爱好者也有帮助。
常量:一小部分缓存的全局内存对所有工作人员可见。如果可以就用它,只读。
全局:慢,所有人可见,读或写。这是您所有数据的结束位置,因此始终需要对其进行一些访问。
本地:您需要在本地群组中分享内容吗?使用本地!您所有的本地工作人员都访问相同的全局内存吗?使用本地! 本地内存仅在本地工作人员内部可见,并且大小有限,但速度非常快。
Private: 只对工作人员可见的内存,将其视为寄存器。默认情况下,所有未定义的值都是私有的。
Say I pass an array of type long and length 10000 to a kernel which I will only use to read, then I would declare it global const as it must be available to all workers and it will not change. Why wouldn't I use the constant qualifier?
实际上,是的,您可以而且应该使用 constant
限定符。它将您的数据放在常量内存中(所有工作人员都可以快速访问的一小部分只读内存)。 GPU 使用它来将制服传输到所有顶点着色器。
When setting the buffer for this array via the CPU, I actually also just could have made the array read-only, which in my eyes says the same as declaring it const. So again, when and why would I declare something constant or global const?
不是真的,当您创建一个只读缓冲区时,您只是向 OpenCL 指定您计划以只读方式使用它,因此它可以在后面进行优化,但您实际上可以从内核写入它。
global const
只是给开发者的一个保障,别不小心写进去了,编译的时候会报错。
基本上,与普通 C 主机端计算相同。如果所有内存都是非常量,程序也能正常工作。
When performing memory-intensive tasks, would it be better to copy the array to a local array inside the kernel? My guess is that local memory would be too small, but what if the array only had a length of 10? When would the array be too big/small? More general: when is it worth copying data from global to local memory?
只有所有工人都读过才有价值。如果每个 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
Say I also want to pass the length of this array, then I would add const int length to the arguments of my kernel, but I'm unsure why I would omit the global qualifier except because I have seen other people do it. After all, length must be accessible for all workers. If I'm right, then length would have a generic address space, but again, I don't really know what that means.
当您没有在内核参数中指定限定符时,它通常默认为 constant
,这是您希望这些小元素能够被所有工作人员快速访问的。
OpenCL 编译器通常遵循的内核参数规则是:如果它仅读取并适合常量,则为常量,否则为全局。