OpenCL 准备好在 CPU 上使用了吗?

Is OpenCL ready for use on CPU?

在实验室中,我们有一个异构集群设置,有许多 Intel CPUs、一些 AMD CPUs 和几个 Nvidia GPU。

对于 HPC 开发,我知道我可以在这个设置上写一次并且 运行 到处都是 OpenCL(甚至 Java ;))。但是在实验室里,我们非常习惯使用 C 或 Fortran 加 MPI 来开发 运行ning 完全在 CPU 上,也许很少有人需要使用 Nvidia 的节点来 运行 CUDA 里的东西。

现在,在开始一个新项目时,我认为能够在 MPI + OpenCL 中编写代码,并且能够在分布式处理中包括 GPU 和 CPUs 会非常好, 运行ning 相同的 OpenCL 代码。那么,是否建议,OpenCL 实施是否已准备好执行此类任务?使用英特尔 SDK 在 CPU 上使用 OpenCL 代码 运行ning,我能否获得与使用英特尔编译器编译的多线程 C 程序一样好的性能?你能指出比较和基准吗?

OpenCL 是可移植的,但不是性能可移植的。您不应该期望 OpenCL 是一次写入-运行-到处都是快速的。为 GPU 编写的 OpenCL 代码可能 运行 在 CPU 上表现不佳,我不希望 GPU 具有统一的性能,尤其是来自不同供应商的 GPU。

为了回答您的具体问题,根据大量第三方评估,不,我不希望 OpenCL 在 Intel CPU 上击败编写良好的 C+OpenMP。这有很多原因。

请注意,由于问题的广泛性,我的回答中的误差线非常大。详细了解您打算计算的内容会很有帮助。

我很幸运地在 CPU 和 GPU 上移植了我的 OpenCL 代码。我的项目是 Levenberg-Marquardt,我首先用 C 编写所有代码以调试它,然后将它移植到 Intel CPU 上的 OpenCL 以检查结果并进行更多调试,然后将其移植到 AMD GPU 上的 OpenCL。

我发现真正跨设备编写好的 OpenCL 代码的最佳技巧是将全局内存缓冲到本地内存,即使您使用的是 CPU,因为这通常是 GPU 上的瓶颈。我在 GPU 与 CPU 上发现的第二个瓶颈是内核大小,CPU 可以处理比 GPU 更大的内核,所以请注意用于常量的内存类型,分配了多少本地内存,等等

已经大约 6 个月了,所以它可能已修复,但 AMD FFT 在 Intel CPU、GPU 和 AMD GPU 上运行良好,但在 NVIDIA GPU 上运行不佳。 AMD 论坛有一个线程,它归因于 NVIDIA 不支持某些矢量功能。

除了其他答案,再次强调一个重点:这个问题很宽泛,性能将取决于许多你在问题中没有提到的因素。您可能已经意识到这些因素,但有疑问,可以在 this answer 中找到摘要(乍一看这个问题似乎无关,并且指的是 CUDA,但许多概念也适用于 OpenCL)

OpenCL 背后的主要驱动思想之一是 heterogeneous computing(值得注意的是,该页面甚至没有提及 OpenCL...)。也就是说,OpenCL 旨在为开发人员提供利用所有可用处理资源的可能性,从单个 ARM 内核到具有数千个内核的多个高端 GPU。

这种多功能性是有代价的。某些概念是为 多核 架构隐式定制的(或者至少,这似乎是迄今为止的主要应用领域)。在任何情况下,"optimizing" OpenCL 程序通常只意味着 "tweaking it in order to run particularly fast on one certain architecture"。矢量化或共享内存之类的东西在一个平台上可能是有利的,但在另一个平台上可能根本不可用。

有一些可能性可以规避这一点,或者至少尝试使一个 OpenCL 程序更多 "agnostic" 它将 运行 使用的硬件。一个明显的选择是查询目标平台属性(例如,首选向量大小或共享内存是否可用),并根据结果启动不同的内核。得益于 OpenCL 中的内置编译器,甚至可以将特定于平台的优化(例如,通过 #defines)包含到内核源代码中。然而,很难对这种优化的工作量与性能增益比做出一般性陈述。而且更难预测 "generic" OpenCL 实现(与经过完美调整的 C 实现相比)可能降低的性能是否迟早会得到补偿,当内核数量增加并且 OpenCL 编译器变得更好时.

所以我的建议是对 "representative" 任务进行一些基准测试,看看性能在不同设备之间是否具有竞争力,请记住每个设备的平均内核数(以及大多数设备的一般异质性可能会增加,而 OpenCL 可能会更容易适应这些变化。