Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;11:线程\本地还是OpenCL 1.2 cl\内核对象的数组?_C++_C++11_Opencl_Gcc4.7 - Fatal编程技术网

C++ C++;11:线程\本地还是OpenCL 1.2 cl\内核对象的数组?

C++ C++;11:线程\本地还是OpenCL 1.2 cl\内核对象的数组?,c++,c++11,opencl,gcc4.7,C++,C++11,Opencl,Gcc4.7,我需要在主机上并行运行几个C++11线程(GCC4.7.1)。他们每个人都需要使用一个设备,比如GPU。根据OpenCL 1.2规范(第357页): 一种优雅的方法是使用thread_local cl_内核对象,我能想到的另一种方法是使用这些对象的数组,这样I'th thread使用I'th对象。由于我之前没有实现这些,我想知道这两种方法中是否有一种是好的,或者是否有更好的方法来完成事情 第三种方法可能是对单个cl_对象使用互斥体,并将其与事件处理程序关联。然后线程可以等待事件完成。不确定这在多

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

一种优雅的方法是使用thread_local cl_内核对象,我能想到的另一种方法是使用这些对象的数组,这样I'th thread使用I'th对象。由于我之前没有实现这些,我想知道这两种方法中是否有一种是好的,或者是否有更好的方法来完成事情


第三种方法可能是对单个cl_对象使用互斥体,并将其与事件处理程序关联。然后线程可以等待事件完成。不确定这在多线程情况下是否有效…

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

如果您真的想在多个线程中使用同一个内核,那么我建议对单个cl_内核对象执行手动同步。如果您不希望线程阻止等待其他线程完成其工作,那么您可以使用异步命令队列和事件在特定线程的工作完成后获得通知(以防止线程排队工作的速度快于GPU的处理速度,当然也可以防止线程回读结果)


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

是的,所有线程都需要使用相同的内核。我看到,对于使用带有异步命令队列的单个内核,我必须使用CPU密集型活动等待或使用C++11条件变量。也许条件变量是一个更好的选择,不是吗?感谢您的详细回复。活动等待(又称忙碌等待)很少是一个好的选择。条件变量(又称信号)总是与互斥体一起工作,在这种情况下,互斥体本身可能已经足够了(一种简单的临界区模式,其中只有一个线程在互斥体上获得锁,而所有其他线程在获得锁之前都会休眠)。但是,确切的锁定策略以及是否值得使用另一种方法(例如,使用两个cl命令队列,一个用于内核执行,另一个用于内存升级/下载),取决于您的具体问题,目前无法回答。假设内核确实需要“相当”的时间来完成这项工作,互斥锁不会序列化代码吗?如果是这样的话,那么一种一次提交所有作业的机制是否会提高性能,因为所有工作项都将执行同一个内核,并且与GPU的SIMD特性兼容,该特性要求一个工作组中的所有工作项执行同一条指令?执行一个内核已经启动了多个“线程”在GPU上并行,具体取决于本地工作组的大小。您应该始终选择最大的工作组,以尽可能多地并行完成工作。这也意味着并行执行多个内核是没有好处的,甚至是不可能的(因为理想情况下,所有处理器都应该分配给单个内核)。从另一个角度来看:如果这些内核需要相当长的时间,并且您的代码依赖于获得执行内核的某些结果,然后你必须等到这些内核完成,不管发生什么。您唯一可以做的就是异步地将工作队列中的工作排队(您仍然必须使用互斥锁,以便只允许一个线程将工作排队),将事件与其关联,然后在CPU线程上执行一些其他工作(如果有),直到事件发出GPU工作完成的信号。同样,这取决于你的精确算法以及谁依赖于谁
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.