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

时间:2015-01-12 13:35:14

标签: c visual-studio-2013 opencl gpu nvidia

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

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

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

3.。)创建 resultSize 容器(inited为零),可以通过原子操作访问(至少我猜这个)

当我的一个工人有结果时,它会将其复制到 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 并且工作人员将在中等待循环。

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

但是我还没有为此实现任何解决方案:

1。)NVIDIA无法无休止地工作,或者至少我无法使用它。当我尝试使用无限循环时,卡崩溃了。

2。)barrier()anf mem_fence()可以管理同步问题但不能管理这个问题

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

NVIDIA opencl有没有睡觉?因为我会把它放到无限循环中,这可能对我有所帮助。

我猜变量结果是一个老问题,必须有好的模式。 我在之前的帖子中遇到了类似的问题(但背景不同)。

4 个答案:

答案 0 :(得分:0)

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

BTW:你确定比较

while (lastPosition **>** RESULT_BUFFER_SIZE)

答案 1 :(得分:0)

您还没有明确表示您使用Windows作为操作系统,但我认为,因为您的问题中包含VS2013标记。

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

答案 2 :(得分:0)

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

如果返回的地址大于缓冲区大小,您可以轻松检查空间何时用完。

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

保持内核在while循环中检查变量,而没有从主机端清空(访问变量)的机制。会使你的内核陷入僵局,并使你的图形崩溃。

如果你想坚持使用OpenCL 1.1,唯一的办法就是运行许多小型内核,然后检查结果。您可以在CPU中处理数据时并行启动更多内核。

答案 3 :(得分:0)

你应该使用OpenCL 2.0和Pipes;他们非常适合这种问题。