有限差分 cuda
资源
论文
3D finite difference computation on GPUs using CUDA
https://app.litmaps.co/seed/2915788706?i=2113190809
cuSten – CUDA Finite Difference and Stencil Library
3D Finite-difference Modeling on a GPU-based Computer using CUDA
总结
做的比较多了。
在使用CUDA实现有限差分方法方面有大量的文献,其中一些例子包括[7]、[8]、[9]、[10]。这些文献通常解释了如何使用CUDA实现有限差分方案的问题,但作者在论文中没有提供公开可用的库或代码供读者在自己的项目中使用,因此需要读者重新编写代码,重复在其他地方已经完成的工作。提供PDE求解器和其他基于模板的计算的库是存在的,比如[11],实际上还有一些可以为程序员生成代码的方法[12],[13],但是这些库和方法可能会因为学习完整的软件包或新方法的投资成本而受到限制。事实上,支持有限差分方法的PETSc库[14],
[15],
[16]现在也提供了GPU的实现,但这限制了程序的编写,主要使用该库的API(从而限制了灵活性),并要求程序员也要开发cuTHRUST[6]的知识来有效实现该库的GPU方面。还可以注意到,PETSc网页[14]目前记录了一些与在PETSc中有效使用GPU有关的困难。因此,我们将cuSten作为PETSc的一个计算框架的补充,对物理学应用感兴趣的程序员可以随时部署,在学习实现大型复杂库方面的开销相对较低。
cuSten
intro
常见问题包括在改变有限差分方案时重新调整边界,或者在计算时确保正确的数据已经加载到GPU上,这两个问题都由cuSten来处理。cuSten旨在通过提供一个新的软件工具来克服这些困难,同时解决上述问题,为程序员实现他们的有限差分求解器引入一组简单的四个函数(在许多情况下为三个)。这些函数的访问方式很像cuBLAS或cuSPARSE,使程序员可以按照自己的选择建立程序,但不需要担心有限差分的具体实现。这个工具允许程序员简单地输入他们所需的有限差分模板和它的应用方向,然后其余的实现,包括领域分解、边界定位和数据处理都被包装成容易调用的函数。这种方法减少了实现新系统/求解器所需的开发时间,并提供了一个强大的框架,不涉及程序员对解决方案的黑箱方法。此外,该方法不需要在学习/实施新工具上投入大量的时间开销。
下面第6节将讨论本方法向三维的扩展。二维问题为开发数值算法提供了一个测试平台,然后可以扩展到三维,而三维的调试、测试和验证更加耗时。下面第6节将讨论本方法向三维的扩展。
在第2节中,我们介绍了cuSten库的底层结构,包括它如何使用流和事件来优化内存管理。然后在第3节软件API和第4节例子中,我们向读者介绍了cuSten的API和例子,以及如果他们想编辑的话,在哪里可以找到库中的所有源代码,API在库本身包含的Doxygen文档中进一步解释。第5节介绍了一个完整的二维Cahn-Hilliard求解器的实现,以及cuSten库的GPU与CPU的基准测试,最后在第6节提出了关于未来潜在工作的结论讨论。
软件架构
本文中的库使用了CUDA编程语言。为了简洁起见,我们假设读者熟悉该语言的标准特性,包括内核、共享内存等。该工具建立在两组主要的代码上,一组处理cuSten_t数据类型的创建和销毁,该数据类型处理所有程序员的输入(在/src/struct中找到),另一组处理计算内核(在/src/kernels中找到)。
在顶层是主程序,解决程序员关心的任何PDE问题,库是通过头文件cuSten.h调用的。程序员使用统一内存向库提供必要的内存和模版细节,这些将在第3节中详细说明。选择统一内存是因为它简化了库中内存的处理以及与程序员其他代码的接口。对超出设备内存限制的数据进行寻址的能力在以下情况下也是很有用的:一个给定的程序所需的所有数据并不适合在设备内存中,内存在设备上的移动和离开由cuSten库来处理,这在下一段有解释。
为了利用统一内存的优势,该库允许程序员将他们的领域划分为 “瓦片”,使每个瓦片都适合设备RAM。每个瓦片是总域在Y方向上的一个块,以确保内存是连续的。这些瓦片被及时加载到GPU上,以便内核启动,这样就不会出现GPU页面故障。程序员也可以选择在某一瓦片的计算完成后将瓦片卸载到主机RAM上,这可能是为了IO,或者如果程序员需要为下一个瓦片或一个新任务释放设备RAM。这个系统确保加载/卸载数据和计算是作为一个流水线实现的,使用单独的数据流加载/卸载和内核启动,确保所有的东西都重叠,并确保尽可能少的时间浪费在PCIe总线上检索内存,这是一个内存约束程序的瓶颈。有限差分程序,如本文讨论的程序,通常是内存约束的,因为每一个数组中的点只需要一些计算,但当几个变量需要应用模板时,内存开销可能相当大。事件被用来确保数据在内核启动前已经被加载。
程序员可以选择提供一个标准的线性模版或者一个带有额外输入系数的函数指针给库,这些例子分别在第4.1节标准权重,4.2节函数指针中讨论。在计算内核中,具有适当边界晕轮的数据块被加载到共享内存中。然后,模版或函数被应用于该块,每个线程计算其位置的输出。当这一切完成后,数据就以块的形式输出到程序员提供的用于输出的内存中,同一内存不能用于这两方面,因为块需要重叠的数据,因此不能使用已经输出的值。
在这一节中,我们提供了一个关于使用图书馆的概述。我们介绍了三个例子。第一个是使用线性模版权重的实现。第二个涉及到一个函数指针,而不是。第三个例子是一个详细的物理问题(流体力学中的平流),包括在这里是为了向用户演示如何在必要时修改源代码。这三个例子(以及更多)可以在examples/src中找到。README中提供了编译的细节。在资源库中的所有例子中,我们采取了各种三角函数的导数,因为这些函数在周期性和非周期性领域都很容易作为基准。
dis & conclusion
6.1. 未来可能对库进行的扩展
如前所述,目前的库仅限于双精度的二维均匀网格。未来的扩展领域可以包括将当前的库函数转移到C++模板中,这将允许更容易地推广到其他的数据类型,而不需要目前手动进行查找和替换。向三维和非均匀网格的扩展就不那么简单了。三维需要采用与目前实现的不同的方法来加载数据,因为数据在RAM中的Z方向上是不连续的,需要采用更复杂的指针加载方案。对于非均匀网格,需要将额外的数据加载到内存中,在这种情况下,有可能采用一种混合的方式来修改代码,比如在WENO的例子中就有额外的数据可用(
和
在WENO的情况下是速度,在非均匀网格的情况下是坐标变换),并使用函数指针,这将是对现有源码的最佳做法。
6.2. MPI
该库的设计适合于MPI域分解,以用于与cuSten库的混合代码。每个MPI进程可以通过设备参数分配给一个GPU,然后用户将应用非周期性的模版,并使用MPI交换边界光晕。由于使用了统一内存,内存交换在MPI中得到了简化,所需的数据将在GPU设备之间直接复制。这使得这个库可以应用于更大的求解器,这些求解器需要的不仅仅是单个的GPU。
6.3. 结束语
在本文中,我们展示了与PETSc等其他最先进的库相比,cuSten如何用于简化CUDA中有限差分程序的实现。cuSten有一个轻量级的界面,作为更广泛项目的一部分,实现这些功能所需的学习曲线最小。该库已经与使用Cahn-Hilliard求解器的串行代码进行了基准测试,并提供了大量的例子来展示潜在用户如何使用所提供的功能。它在有限差分求解器的开发和需要基于模板操作的更多领域,如图像处理和优化问题,有广泛的应用。
代码
更多推荐
所有评论(0)