OpenCL:如何在JOCL中使用本地内存

时间:2012-01-07 03:37:05

标签: memory opencl jocl

假设我想对大型固定对象执行并行计算,例如:固定的大型稀疏(定向)图形或任何类似的对象。

要对此图形或对象进行任何合理的计算,例如图形中的随机遍历,将图形放在全局内存中可能是出于速度原因而无法解决的问题。

留下本地/私人记忆。如果我已经理解GPU架构是正确的,那么本地或私有内存的(只读)访问之间几乎没有速度差异,这是正确的吗?我不愿意将图形复制到私有内存,因为这意味着每个工作单元都必须存储整个图形,这可能会很快耗尽GPU的内存(对于非常大的图形甚至可以减少核心数量)可以使用和/或使操作系统不稳定。)

所以,假设我在本地与私人的阅读速度上是正确的,我该如何在实践中这样做?如果是为了简化,我将图形缩减为int[] fromint[] to(存储每个有向边的开始和结束),我当然可以使内核看起来像这样

computeMe(__local const int *to, __local const int *from, __global int *result) {
     //...
}

但是我没有看到我应该如何从JOCL调用它,因为那里没有给出private / local / global修饰符。

是否将局部变量自动写入每个本地工作组的内存?或者这是如何工作的?我根本不清楚我应该如何正确地进行这种记忆分配。

2 个答案:

答案 0 :(得分:3)

您无法从主机传递本地内存参数的值。主机无法读/写本地内存。要使用本地内存,您仍需要将数据作为全局传递,然后在使用之前从全局复制到本地。这只有在您多次读取数据时才有用。

恒定记忆怎么样?如果您的输入数据没有变化且不太大,那么将输入数据放入常量内存可能会给您带来相当大的加速。可用的常量内存通常约为16K到64K。

computeMe(__constant int *to, __constant int *from, __global int *result) {
 //...
}

编辑(添加引用):

有关在OpenCL中使用__本地内存的示例,请参阅here

对于NVidia硬件,更多性能详细信息为NVidia OpenCL best practices guide (PDF)。在那里,有关于内存类型之间性能差异的更多信息。

答案 1 :(得分:1)

您写道“出于速度原因,将图表放在全局内存中可能是不可能的。” - 你没有太多其他选择。我的意思是数据通常在全局内存中。

(作为旁注 - 在特殊情况下,您可能会将其重新构造为纹理(如果元素格式合适)。此外,nvidia上的所谓“常量”内存针对“广播”类型的操作进行了优化,这意味着所有线程都读取来自同一地点,我想情况并非如此。我建议在开始时远离这些类型。)

好的,作为建议,首先尝试使用'全局记忆'。 本地内存的“生存期”仅在内核执行期间。只有当您多次重复使用相同的数据元素时,才有理由这样做(将其视为一个显式预加载的缓存)。

本地mem也限制在大约16-48k字节,因此它只能存储一部分数据。尝试在适合这些块的子图中分解图形。

在你的表示中,你可以将边缘(从[],到[])划分为固定大小的组。

通用模式是

步骤1.从全局复制到本地

your_local_array [get_local_id(0)] = input_global_mem [get_global_id(0)]

步骤2.确保每个线程都执行操作 障碍(当地记忆围栏)

现在,工作项(线程)可以在本地内存中加载的子图上工作。

请记住,本地mem只包含整个图形的有限部分。 如果您需要从任何线程访问任意节点,则上述模式将无法使用。

我建议开始使用算法进行实验而不使用本地内存(直接从全局读取)并确保它正常工作(通常在路上会有一些惊喜)。 稍后您可以识别可能存储在本地存储器中的数据部分以加快速度。