从程序员的角度来看,CUDA和OpenCL在2013年末之间如何比较?我的小组正在考虑尝试利用GPU计算。通过选择仅支持OpenCL但不支持CUDA的硬件,我们是否会大大限制自己?
具体来说,以下假设是否正确?
CUDA中所有可能的功能在OpenCL中也可能
只要我们不使用库,给定的任务就不会很容易(或更难)地完成
CUDA的主要优势是库的可用性
两者都对所有三个主要平台(Win / OSX / Linux)都具有良好的支持。
从程序员的角度来看,CUDA和OpenCL在2013年末之间如何比较?我的小组正在考虑尝试利用GPU计算。通过选择仅支持OpenCL但不支持CUDA的硬件,我们是否会大大限制自己?
具体来说,以下假设是否正确?
CUDA中所有可能的功能在OpenCL中也可能
只要我们不使用库,给定的任务就不会很容易(或更难)地完成
CUDA的主要优势是库的可用性
两者都对所有三个主要平台(Win / OSX / Linux)都具有良好的支持。
Answers:
我将尝试总结在开发ViennaCL的过程中获得的经验,在这些过程中,我们拥有CUDA和OpenCL后端,其中大部分都是许多计算内核的1:1翻译。根据您的问题,我还将假设我们在这里主要使用GPU。
性能可移植性。首先,就您一次编写一个内核而言,它没有性能可移植的内核之类的东西,它可以在每种硬件上高效运行。由于支持的硬件范围更广,因此在OpenCL中更明显,但在CUDA中却没有。在CUDA中,由于所支持的硬件范围较小,因此不太明显,但是即使在这里,我们也必须区分至少三种硬件体系结构(Fermi之前的版本,Fermi和Kepler)。这些性能波动很容易导致20%的性能变化,这取决于您如何协调线程和选择的工作组大小,即使内核像缓冲区副本一样简单。值得一提的是,在Fermi之前的GPU和Fermi的GPU上,可以直接在CUDA中直接编写快速矩阵乘法内核,对于最新的Kepler GPU,似乎必须使用PTX伪汇编语言才能接近CUBLAS的性能。因此,即使是由供应商控制的语言,例如CUDA,似乎也存在与硬件开发保持同步的问题。此外,当您运行nvcc时,所有CUDA代码都会被静态编译,这在某种程度上需要通过-arch标志进行平衡,而OpenCL内核是在运行时从即时编译器进行编译的,因此您原则上可以定制内核具体到特定计算设备的细节。但是,后者相当复杂,通常仅在代码成熟和经验积累时才成为非常有吸引力的选择。要付出的代价是即时编译所需的O(1)时间,在某些情况下这可能是个问题。OpenCL 2。
调试和分析。CUDA调试和性能分析工具最适合GPGPU。AMD的工具也不错,但它们不包括cuda-gdb或cuda-memcheck之类的工具。此外,NVIDIA仍然为GPGPU提供了最强大的驱动程序和SDK,由于漏洞多多的内核而导致的系统冻结实际上是OpenCL和CUDA的例外,而不是常规。由于某些原因,在这里我可能不需要解释,NVIDIA不再为带有CUDA 5.0及更高版本的OpenCL提供调试和配置文件。
可达性和便利性。启动和运行第一个CUDA代码要容易得多,特别是因为CUDA代码与主机代码很好地集成在一起。(我将讨论以后要支付的价格。)网上有很多教程以及优化指南和一些库。使用OpenCL,您必须经过大量的初始化代码并以字符串形式编写内核,因此,在将源提供给jit编译器时,您只会在执行过程中发现编译错误。因此,使用OpenCL进行一个代码/编译/调试周期需要更长的时间,因此在此初始开发阶段,您的生产率通常较低。
软件库方面。尽管先前的项目都支持CUDA,但对于OpenCL来说,与其他软件的集成是一大优势。您可以通过仅链接共享的OpenCL库来使用OpenCL,就是这样,而使用CUDA时,则需要具有整个CUDA工具链。更糟糕的是,您需要使用正确的主机编译器才能使nvcc正常工作。如果您曾经尝试在GCC 4.6或更高版本中使用CUDA 4.2,那么您将很难工作。通常,如果您碰巧使用了比CUDA SDK更新的任何编译器,则可能会出现问题。集成到诸如CMake的构建系统中是另一个令人头痛的原因(您也可以在例如PETSc上找到足够的证据邮件列表)。在您拥有完全控制权的您自己的计算机上,这可能不是问题,但是一旦您分发代码,就会遇到用户在其软件堆栈中受到某些限制的情况。换句话说,使用CUDA,您不再有选择自己喜欢的主机编译器的权限,而是由NVIDIA规定允许使用哪些编译器。
其他方面。CUDA与硬件(例如,翘曲)有点接近,但是我对线性代数的经验是,您很少会从中受益。CUDA还有更多的软件库,但是越来越多的库使用多个计算后端。同时,ViennaCL,VexCL或Paralution都支持OpenCL和CUDA后端,其他领域的图书馆也可以看到类似的趋势。
GPGPU不是银弹。事实证明,GPGPU可为结构化操作和计算受限的任务提供良好的性能。但是,对于顺序处理所占份额不可忽略的算法,GPGPU无法神奇地克服阿姆达尔定律。在这种情况下,最好使用可用的最佳算法的良好CPU实现,而不是尝试抛出并行但不太合适的算法来解决问题。另外,PCI-Express是一个严重的瓶颈,因此您需要预先检查GPU的节省是否可以补偿来回移动数据的开销。
我的建议。请考虑使用CUDA 和 OpenCL而不是CUDA 或OpenCL的。无需不必要地将自己限制在一个平台上,而可以从两全其美中受益。对我而言,最有效的方法是在CUDA中设置初始实现,对其进行调试,对其进行概要分析,然后通过简单的字符串替换将其移植到OpenCL。(您甚至可以参数化OpenCL内核字符串生成例程,以便具有一定的灵活性。通常需要花费不到10%的时间,但是您也可以在其他硬件上运行。您可能会对非NVIDIA硬件在某些情况下的性能表现感到惊讶。最重要的是,应考虑最大程度地重用库中的功能。快速而 对某些功能进行肮脏的重新实现通常可以在CPU上的单线程执行中接受,但在大规模并行硬件上的性能通常很差。理想情况下,您甚至可以将所有内容卸载到库中,而不必担心它们在内部使用CUDA,OpenCL还是同时使用这两者。就我个人而言,从现在开始几年后,我永远都不敢为我想依赖的东西编写供应商锁定的代码,但是这个思想方面应该单独讨论。