OpenCL:__常量vs.__本地?

OpenCL:__常量vs.__本地?,opencl,gpgpu,Opencl,Gpgpu,假设我有一个很大的值数组(仍然小于64 kB),它通常在内核中读取,但不写入。然而,它可以从外部改变。数组有两组值,让我们分别称它们为left和right。 所以问题是,将大数组作为_全局数组并将其写入_局部左数组和_局部右数组是否更快;或者将其作为常量uu常量大并在内核中处理访问?例如: __kernel void f(__global large, __local left, __local right, __global x, __global y) { for(int i; i

假设我有一个很大的值数组(仍然小于64 kB),它通常在内核中读取,但不写入。然而,它可以从外部改变。数组有两组值,让我们分别称它们为left和right。 所以问题是,将大数组作为_全局数组并将其写入_局部左数组和_局部右数组是否更快;或者将其作为常量uu常量大并在内核中处理访问?例如:

__kernel void f(__global large, __local left, __local right, __global x, __global y) {
    for(int i; i < size; i++) {
        left[i] = large[i];
        right[i] = large[i + offset];
    }
    ...
    x = foo * left[idx];
    y = bar * right[idx];
}
(索引有点复杂,但可以用宏来创建) 我读到恒定的记忆存在于全球空间中,那么它应该慢一点吗?
它将在Nvidia卡中运行。

首先,在第二种情况下,您应该有某种方法使结果可供您的CPU使用。我假设您在计算后复制回一个
全局
空间

我认为这取决于你在内核中做了什么。例如,如果您的内核计算量很大(每个线程都要进行大量计算),那么第一个选项可能会带来额外的开销。为什么?

  • 您需要花费一些时间将数据从
    全局大空间
    复制到
    本地空间
    左侧空间和
    右侧空间
    -可以接受
  • 你对局部空间的数据做了大量的计算-好的
  • 您需要花一些时间从
    本地
    左侧
    右侧
    复制回
    全局
    大型
    -可以接受
然而,如果内核相对较轻,即每个线程将进行一些小计算,那么

  • 您可以使用
    常量
    空间中的数据进行一些计算。这很可能意味着你不需要经常访问它
  • 将中间结果存储在局部空间中
  • 您需要花费一些时间从
    本地
    空间复制回
    全局
    空间。-可以接受
总而言之,对于大内核,第一种选择更好。对于小的内核第二

还有一点需要注意的是,如果你有多个内核一个接一个地在
large
上工作,那么一定要选择第一个选项。因为这样您就可以将数据保存在全局内存空间中,而不必每次启动内核时都进行复制


编辑:既然你说它经常被访问,那么我想你应该选择第一个选项。

嗨,谢谢,我明白你的意思,但是
left
right
large
的值不会复制回CPU。为了澄清这一点,请想象变量
x
y
是计算的对象,而
大的
数组只是一些权重。
x
y
(不只是两个,有很多)在GPU上,内核被多次调用,最后只有
x
y
被读回CPU。哦,我明白了。那么选项二可能更好,因为全局内存中不需要“大”。大多数GPU都有专门的缓存,用于恒定的内存空间。所以它会有回报的。仅供参考,在OpenCL关键字之前不再需要两个下划线,“常量”现在与“常量”相同。另外,根据我的经验,大多数情况下,对于不太繁琐的算法,很难估计性能。更不用说一种架构的优化对另一种架构来说可能是噩梦。因此,要回答您的问题,您必须卷起袖子,同时实现并测试:)。非常感谢,我不知道“\uuuuu”是可选的,它肯定会节省一些工作。是的,我们把代码作为第一个选项来实现,并且正在讨论可能使用常量重新实现它,我想我们只需要尝试一下:P
__kernel void f(__constant large, __global x, __global y) {
    ...
    x = foo * large[idx];
    y = bar * large[idx * offset];
}