2

我需要在主机中并行运行几个 C++11 线程(GCC 4.7.1)。他们每个人都需要使用一个设备,比如 GPU。根据 OpenCL 1.2 规范(第 357 页):

All OpenCL API calls are thread-safe75 except clSetKernelArg. 
clSetKernelArg is safe to call from any host thread, and is safe
to call re-entrantly so long as concurrent calls operate on different
cl_kernel objects. However, the behavior of the cl_kernel object is
undefined if clSetKernelArg is called from multiple host threads on
the same cl_kernel object at the same time.

一种优雅的方法是使用 thread_local cl_kernel 对象,而我能想到的另一种方法是使用这些对象的数组,以便第 i 个线程使用第 i 个对象。由于我之前没有实现这些,我想知道这两者中的任何一个是否很好,或者是否有更好的方法来完成任务。

第三种方法可能是对单个 cl_object 使用互斥体并将其与事件处理程序相关联。然后线程可以等到事件完成。不确定这是否适用于多线程情况......

4

1 回答 1

3

主要问题是所有这些线程是否需要使用相同的内核,或者是否每个线程都有自己不同的内核。您使用 thread_local cl_kernel 对象或 n 个内核对象数组的想法都会导致创建 n 个内核对象,并且从 OpenCL 的角度来看同样好。但是,如果它们都包含相同的代码,那么您将不必要地浪费空间/导致上下文切换/混乱缓存/......并且可以与将应用程序二进制文件多次加载到内存中而不共享恒定的二进制代码段相媲美。

如果您确实想在多个线程中使用相同的内核,那么我建议您对单个 cl_kernel 对象执行手动同步。如果您不希望您的线程阻塞等待直到其他线程完成它们的工作,您可以使用异步命令队列和事件在特定线程的工作完成后得到通知(以防止线程比 GPU 更快地排队工作可以处理它或读回结果当然)。

如果您的线程要执行不同的内核程序,那么我建议为每个线程创建一个单独的命令队列以简化执行。如果您选择将这些对象句柄存储在线程本地存储、全局数组或其他地方,这完全取决于您吗?

于 2012-10-08T00:15:49.410 回答