并行化应用程序:
确定了热点并完成了设定目标和期望的基本练习后,开发人员需要对代码进行并行化。 根据原始代码,这可以像调用现有的GPU优化库(如cuBLAS,cuFFT或Thrust)一样简单,也可以像向并行编译器添加一些预处理器指令那样简单。
另一方面,一些应用程序的设计需要一些重构来展现其固有的并行性。 由于即使将来的CPU架构也需要公开这种并行性以改进或简单地维持顺序应用的性能,因此CUDA并行编程语言系列(CUDA C / C ++,CUDA Fortran等)旨在尽可能简化这种并行性的表达,同时使支持CUDA的GPU能够在最大并行吞吐量的情况下运行。
入门:
并行化顺序代码有几个关键策略。 尽管如何将这些策略应用到特定应用程序的细节是一个复杂且具有问题特征的主题,但无论我们是否并行化运行在多核CPU上的代码或在CUDA GPU上使用的代码,此处列出的一般主题都适用。
并行库:
并行化应用程序最直接的方法是利用现有的库,代表我们利用并行体系结构。 CUDA工具包包括许多已针对NVIDIA CUDA GPU进行微调的库,例如cuBLAS,cuFFT等。
这里的关键是,库在与应用程序的需求相匹配时最有用。 例如,已经使用其他BLAS库的应用程序通常可以很容易地切换到cuBLAS,而对于线性代数几乎没有的应用程序对cuBLAS几乎没有用处。 其他CUDA工具包库也是如此:cuFFT具有类似于FFTW等的界面。
还值得注意的是Thrust库,它是一个类似于C ++标准模板库的并行C ++模板库。 Thrust提供了丰富的数据并行基元集合,如扫描,排序和缩减,它们可以组合在一起以实现具有简洁可读源代码的复杂算法。 通过根据这些高级抽象描述您的计算,您可以为Thrust提供自动选择最有效的实现的自由。 因此,Thrust可用于程序员生产力最重要的CUDA应用程序的快速原型开发,以及坚固性和绝对性能至关重要的生产。
并行化编译器:
顺序代码并行化的另一种常见方法是利用并行化编译器。 通常这意味着使用基于指令的方法,程序员使用编译指示或其他类似的符号向编译器提供关于何处可以找到并行性的提示,而无需修改或修改底层代码本身。 通过向编译器公开并行性,指令允许编译器执行将计算映射到并行体系结构的详细工作。
OpenACC标准提供了一组编译器指令,用于指定标准C,C ++和Fortran中的代码循环和区域,这些代码应该从主机CPU卸载到附加的加速器(如CUDA GPU)。 管理加速器设备的细节由OpenACC启用的编译器和运行时隐式处理。
编码揭示并行性:
对于需要超出现有并行库或并行编译器可提供的附加功能或性能的应用程序而言,并行编程语言(如CUDA C / C ++)与现有的顺序代码无缝集成是必不可少的。
一旦我们在应用程序的配置文件评估中找到热点并确定自定义代码是最好的方法,我们就可以使用CUDA C / C ++将我们代码的那部分内容的并行性暴露为CUDA内核。 然后,我们可以将此内核启动到GPU上,并检索结果,而无需对我们的其他应用程序进行重大改写。
当我们的应用程序的总运行时间的大部分花费在代码的一些相对孤立的部分中时,这种方法是最直接的。 更难以并行化的是具有非常平坦的轮廓的应用程序 - 即,花费的时间相对均匀地分布在宽广的代码库部分的应用程序。 对于后一种应用程序,可能需要一定程度的代码重构来暴露应用程序中固有的并行性,但请记住,此重构工作将趋于惠及所有未来体系结构,CPU和GPU等,因此它非常值得 应该有必要的努力。