假设我想对大型固定对象执行并行计算,例如:固定的大型稀疏(定向)图形或任何类似的对象。
要对此图形或对象进行任何合理的计算,例如图形中的随机遍历,将图形放在全局内存中可能是出于速度原因而无法解决的问题。
留下本地/私人记忆。如果我已经理解GPU架构是正确的,那么本地或私有内存的(只读)访问之间几乎没有速度差异,这是正确的吗?我不愿意将图形复制到私有内存,因为这意味着每个工作单元都必须存储整个图形,这可能会很快耗尽GPU的内存(对于非常大的图形甚至可以减少核心数量)可以使用和/或使操作系统不稳定。)
所以,假设我在本地与私人的阅读速度上是正确的,我该如何在实践中这样做?如果是为了简化,我将图形缩减为int[] from
和int[] to
(存储每个有向边的开始和结束),我当然可以使内核看起来像这样
computeMe(__local const int *to, __local const int *from, __global int *result) {
//...
}
但是我没有看到我应该如何从JOCL调用它,因为那里没有给出private / local / global修饰符。
是否将局部变量自动写入每个本地工作组的内存?或者这是如何工作的?我根本不清楚我应该如何正确地进行这种记忆分配。
答案 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只包含整个图形的有限部分。 如果您需要从任何线程访问任意节点,则上述模式将无法使用。
我建议开始使用算法进行实验而不使用本地内存(直接从全局读取)并确保它正常工作(通常在路上会有一些惊喜)。 稍后您可以识别可能存储在本地存储器中的数据部分以加快速度。