OpenCL 从 GPU 读取可变大小的结果缓冲区

OpenCL read variable size result buffer from the GPU

我有一个搜索 OpenCL 1.1 算法,它适用于少量数据:

1.) 构建 inputData 数组并将其传递给 GPU

2.) 创建一个非常大的 resultData 容器(例如 200000 * sizeof (cl_uint) )并传递这个

3.) 创建可以通过原子操作访问的 resultSize 容器(初始化为零)(至少我这么认为)

当我的一个工作人员得到结果时,它会将结果复制到 resultData 缓冲区并在原子 inc 操作中递增 resultSize (直到缓冲区已满)。

我来写个代码示例(opencl代码):

lastPosition = atomic_add(resultBufferSize, 5);
while (lastPosition > RESULT_BUFFER_SIZE)
{
    lastPosition = atomic_add(resultBufferSize, 5);
}

在主机端,我读取缓冲区并将 resultBufferSize 设置为零:

resultBufferSize = 0;
oclErr |= clEnqueueWriteBuffer(gpuAcces.getCqCommandQueue(), cm_resultBufferSize,  CL_TRUE, 0,  sizeof(cl_uint), (void*)&resultBufferSize, 0, NULL, NULL);

现在我的问题是:

我的结果比 resultData 可以存储的多得多。无论如何,我不知道结果的大小(例如,我能找到多少条路径)。

我的想法:

有时我会清空(或处理)主机端的容器并在缓冲区已满时重置 resultSize,工作人员将在 while 循环.

我喜欢这个想法,因为我也可以在主机上并行处理数据。

但是我还不能为此实施任何解决方案:

1.) NVIDIA 无法使用 endless while 或至少我无法使用它。当我尝试使用无限循环时,卡崩溃了。

2.) barrier() anf mem_fence() 可以管理同步问题,但这个不行

您是否有任何可靠的想法我可以如何处理不固定的结果大小(例如在搜索问题期间)?我几乎可以肯定一定有一个好的模式,但我找不到它。

NVIDIA opencl有sleep吗?因为我会把它放入无限循环中,所以也许这会对我有所帮助。

我猜可变结果是个老问题,一定有好的模式。 我在之前的 post 中遇到过类似的问题(但上下文不同)。

我有一个关于可变问题大小的类似问题。一种方法可能是简单地实施分而治之的方法并在主机上拆分数据。您可以在设备上一个接一个地处理您的数据块。

顺便说一句:你比较确定

while (lastPosition **>** RESULT_BUFFER_SIZE)

您没有明确指出您将 Windows 用作 OS 但我认为是因为您的问题中有 VS2013 标签。

Nvidia 卡没有崩溃。在 Windows 上,WDDM 驱动程序中有 Timeout Detection & Recovery (TDR),如果 GPU 驱动程序变得无响应,它会重新启动它们。您可以使用 Nsight 轻松禁用此 "feature"。但是,请注意这可能会导致您的桌面环境出现问题,因此请确保编写的内核将在可容忍的时间内结束。然后,即使在 Windows 上使用 Nvidias OpenCL 实现,您也可以 运行 非常长的内核。

为什么不在全局变量上使用 addr = atomic_add(&addr_counter, 1);,并使用返回的地址写入另一个全局缓冲区 buffer[addr*2] = X; buffer[addr*2+1] = Y;

如果返回的地址大于缓冲区大小,您可以轻松检查何时 运行 超出 space。

编辑:您想要的是并行内核执行和数据访问,这在 OpenCL 1.1 中是不可能的。您应该选择具有该功能(SVM 或管道)的 OpenCL 2.0。

将内核保持在 while 循环中检查变量,并且没有从主机端清空(访问变量)的机制。将使您的内核死锁,并使您的图形崩溃。

如果你想坚持使用 OpenCL 1.1,唯一的方法是 运行 许多小尺寸的内核,然后检查结果。在 CPU.

中处理该数据时,您可以并行启动更多内核

您应该使用 OpenCL 2.0 和管道;它们非常适合此类问题。