Tro*_*vey 4 concurrency opencl libdispatch grand-central-dispatch objective-c-blocks
随着 OpenCL 2.0 的推出,OpenCL 似乎具备了 Grand Central Dispatch (GCD) 的许多特性,例如 CLang/Apple 风格的块和队列。查看它们各自的功能集,我想知道 OpenCL 是否可以完成 GCD/libdispatch 可以做的所有事情,但是增加了将计算引导到 GPU 和 CPU 的能力——或者 GCD 是否可以提供更多与众不同的功能来自 OpenCL。
具体我的问题是:
GCD 和 OpenCL 的并发特性有什么区别?
如果一起使用它们有价值(假设 GCD 提供附加功能),C 块是否可以路由到 GCD 队列或 OpenCL 队列?如果以 CPU 为目标,是否有理由通过 OpenCL 与直接运行
OpenCL 2.0 是否提供 GCD 风格的负载平衡,可以填充跨越 CPU 和 GPU 的线程?
小智 5
在目前的形式中,OpenCL 能够解决数据并行和任务并行问题,正如用于排队工作的不同 OpenCL API 原语所证明的那样:
clEnqueuNDRangeKernel: 用于将具有 N 维工作组大小的内核排队。通常用于数据并行处理。clEnqueueTask: 用于将包含单个工作项的内核排入队列。这个原语用于任务并行执行,本质上等同于clEnqueueNDRangeKernel全局工作大小为 1。它已从 OpenCL 2.0 规范中删除clEnqueueNativeKernel将本机 C/C++ 函数排队到设备(如果它支持本机内核),好处是您可以使用排队机制(和队列中的排序)并直接从 OpenCL 上下文访问缓冲区数据。除此之外,这与线程或任务的概念非常相似。因此,虽然 OpenCL 显然起源于 GPU 上的数据并行处理,并且仍然最适合处理可以以某种方式强制在 1、2 或 3 维网格中的数据,但面向任务的处理也是可能的。一旦开始针对具有多个 CPU、GPU、DSP 和加速器的异构系统,优势就会变得更加明显,因为 OpenCL 可以通过一种形式来针对所有这些设备。
另一方面,GCD 提供了一个方便的库,通过构建队列(不同类型和优先级)的概念,可以减轻开发人员管理和调度任务的负担。因此,使用 GCD 可以在对称多处理系统上减少出错的可能性和更紧凑的代码。
因此,虽然 OpenCL 和 GCD 的起源有不同的背景(除了它们都来自 Apple 的事实),但它们都在其基础上使用队列来管理工作项分发。他们都有一个“上下文”的概念来定义数据访问。
从 OS X 版本 10.7 开始,可以使用 GCD 将 OpenCL 内核(类似于块)分派到支持 OpenCL 的设备,从而有可能结合 OpenCL 和 GCD 的优点/优势。
以下是针对您的具体问题的一些答案/见解的尝试:
1 - GCD 和 OpenCL 的并发特性有何不同?
正如@Dithermaster 和@sharpneli 所指出的,GCD 最初的目标是面向任务(对称多)处理,而 OpenCL 最初是用于异构架构上的数据并行处理。
OpenCL 和 GCD 之间的主要区别之一在于排队机制。例如,虽然 OpenCL 和 GCD 都支持同步和异步执行,但 GCD 对全局异步队列具有三个优先级。OpenCL 运行时没有这个(它有工作项的乱序执行,但没有定义运行时将首先执行哪些工作项)。
GCD 手册还指出任务比传统线程更轻量级,这使得生成 GCD 任务的指令比线程少得多。
另一个区别在于所使用的内存一致性模型。OpenCL 对内核使用宽松的模型,具有全局、本地、私有和常量内存。GCD 没有这个。
另一方面,OpenCL 具有向量数据类型和向量内在函数,允许在不依赖编译器的情况下直接挖掘架构的 SIMD 潜力。在某些架构上,这是有益的,而其他架构(如 MIC)建议不要手动矢量化。
最后 - 虽然不是真正的并发功能 - OpenCL 具有允许读取和写入图像类型的功能,基本上可以让您直接访问纹理内存。即使对于与图像处理无关的算法,这通常也可用于获得显着的加速。
2 - 如果一起使用它们有价值(假设 GCD 提供附加功能),C 块是否可以路由到 GCD 队列或 OpenCL 队列?如果以 CPU 为目标,是否有理由通过 OpenCL 与直接运行
通过同时使用 GCD 和 OpenCL,您可以处理任何支持 OpenCL 的设备。因此,您可以使用平台潜在的异构特性,同时仍然能够从 GCD 提供的更高级别的机制中受益,使多线程更容易。使用 OpenCL C API(甚至 C++ API)编写所有内容可能会导致代码稍微多一些。
此外,GCD 提供的原语gcl_get_kernel_block_workgroup_info可以为您的内核推荐最佳工作组大小。
但是,根据我的理解,不可能将任意 C 块路由到 GCD 或 OpenCL 队列。C 块只能进入非 OpenCL 队列。OpenCL 内核只能(从主机端)分派到支持 OpenCL 的设备的队列。从设备端(因此从 OpenCL 内核中),一个块只能被分派到同一个设备。
3 - OpenCL 2.0 是否提供 GCD 风格的负载平衡,可以填充跨越 CPU 和 GPU 的线程?
不,OpenCL 2.0 并没有真正定义如何进行负载均衡,无论是从主机的角度还是从设备的角度。
然而,在主机端,可以很容易地拆分计算并在 CPU 上运行它的一部分,在一个或多个 GPU 上运行另一部分。一种方法是调整工作组大小和工作组偏移量,并仅复制每个设备所需的最少数据。然后可以使用自动调整机制来确定所使用的不同设备之间的最佳负载平衡。
一旦 OpenCL 2.0 驱动程序可用,新引入的管道、动态并行和共享虚拟内存将为在设备之间有效地划分工作提供更多可能性。目前尚不清楚这些功能是否以及如何通过 GCD 提供。