首先,你应该意识到CUDA不会自动使计算更快的事实。一方面,因为GPU编程是一门艺术,它可以非常,非常具有挑战性得到正确。另一方面,因为GPU仅仅适合于某些类型的计算。
这听起来很混乱,因为你基本上可以计算GPU上的任何东西。关键点是,当然,你是否将实现一个良好的加速。这里最重要的分类是问题是任务并行还是数据并行。第一个大致是指几个线程或多或少独立地在自己的任务上工作的问题。第二个是指许多线程都在做相同的问题 – 但是在数据的不同部分。
后者是GPU的优点:它们有许多核心,并且所有核心都是相同的,但是对输入数据的不同部分进行操作。
你提到你有“简单的数学,但有大量的数据”。虽然这可能听起来像一个完美的数据并行问题,因此它非常适合GPU,还有另一个方面要考虑:GPU在理论计算能力(FLOPS,每秒浮点运算)方面是非常快的。但是它们经常被存储器带宽限制。
这导致另一种问题分类。即是问题是内存限制还是计算限制。
第一种是指针对每个数据元素完成的指令数量低的问题。例如,考虑并行向量相加:你必须读取两个数据元素,然后执行一个单独的加法,然后将和写入结果向量。在GPU上执行此操作时,您将看不到加速,因为单个添加不会补偿读取/写入内存的努力。
socond术语“计算界限”是指与存储器读/写的数量相比指令的数量较高的问题。例如,考虑矩阵乘法:当n是矩阵的大小时,指令的数量将是O(n ^ 3)。在这种情况下,可以预期GPU将以特定矩阵尺寸优于CPU。另一个示例可以是当对“少数”数据元素执行许多复杂的三角计算(正弦/余弦等)时。
作为经验法则:您可以假设从“主”GPU内存读取/写入一个数据元素的延迟大约为500条指令….
因此,GPU性能的另一个关键点是数据本地性:如果你必须读取或写入数据(在大多数情况下,你必须;-)),那么你应该确保数据保持尽可能接近可能对GPU核心。 GPU因此具有通常仅具有几个KB大小,但对于将要参与计算的数据特别有效的某些存储器区域(称为“本地存储器”或“共享存储器”)。
所以再次强调这一点:GPU编程是一种艺术,只是远程与CPU上的并行编程有关。像Threads在Java,所有的并发基础设施,如ThreadPoolExecutors,ForkJoinPools等可能给人的印象是,你只需要拆分你的工作,以某种方式,并将其分布在几个处理器。在GPU上,您可能在低得多的层面遇到挑战:占用率,寄存器压力,共享内存压力,内存合并…仅举几例。
然而,当你有一个数据并行,计算绑定问题要解决,GPU是要走的路。
一般注释:您特别要求CUDA。但我强烈建议你也看看OpenCL。它有几个优点。首先,它是一个独立于供应商的开放工业标准,并且AMD,苹果,英特尔和NVIDIA都有OpenCL的实现。此外,在Java世界中对OpenCL有更广泛的支持。我只想使用CUDA运行时库,例如CUFFT用于FFT或CUBLAS用于BLAS(Matrix / Vector操作)。虽然有为OpenCL提供类似库的方法,但是它们不能直接从Java端使用,除非您为这些库创建自己的JNI绑定。
你也许会发现有趣的是,在2012年10月,OpenJDK HotSpot小组开始了项目“苏门答腊”:http://openjdk.java.net/projects/sumatra/。这个项目的目标是直接在JVM中提供GPU支持,并得到JIT的支持。当前状态和第一个结果可以在他们的邮件列表http://mail.openjdk.java.net/mailman/listinfo/sumatra-dev看到
然而,一段时间以前,我收集了一些与“Java on the GPU”相关的资源。我将在这里再次总结,没有特定的顺序。
(字节)代码翻译和OpenCL代码生成:
https://github.com/aparapi/aparapi:由AMD创建和积极维护的开源库。在特殊的“Kernel”类中,可以重写应该并行执行的特定方法。此方法的字节代码在运行时使用自己的字节码读取器加载。代码被转换为OpenCL代码,然后使用OpenCL编译器进行编译。然后,结果可以在OpenCL设备上执行,OpenCL设备可以是GPU或CPU。如果编译成OpenCL是不可能的(或没有OpenCL可用),代码将仍然使用线程池并行执行。
https://github.com/pcpratts/rootbeer1:用于将Java的一部分转换为CUDA程序的开源库。它提供专用接口,其可以被实现以指示应当在GPU上执行某个类。与Aparapi相反,它尝试自动将“相关”数据(即对象图的完整相关部分)序列化为适合GPU的表示。
http://code.google.com/p/java-gpu/:用于将带注释的Java代码(有一些限制)翻译为CUDA代码的库,然后将其编译为在GPU上执行代码的库。图书馆是在博士论文的背景下开发的,其中包含有关翻译过程的深刻背景信息。
https://github.com/ochafik/ScalaCL:OpenCL的Scala绑定。允许与OpenCL并行处理特殊的Scala集合。在集合的元素上调用的函数可以是通常的Scala函数(有一些限制),然后将其转换为OpenCL内核。
语言扩展
http://www.ateji.com/px/index.html:Java的语言扩展,允许使用OpenCL在GPU上执行的并行构造(例如并行for循环,OpenMP样式)。不幸的是,这个非常有前途的项目已不再保持。
http://www.habanero.rice.edu/Publications.html(JCUDA):一个库,可以将特殊的Java代码(称为JCUDA代码)转换为Java和CUDA-C代码,然后可以在GPU上编译和执行。然而,图书馆似乎不是公开的。
Java的OpenCL / CUDA绑定库
https://github.com/ochafik/JavaCL:OpenCL的Java绑定:面向对象的OpenCL库,基于自动生成的低级绑定
http://jogamp.org/jocl/www/:OpenCL的Java绑定:面向对象的OpenCL库,基于自动生成的低级绑定
http://www.lwjgl.org/:OpenCL的Java绑定:自动生成的低级绑定和面向对象的方便类
http://jocl.org/:OpenCL的Java绑定:低级绑定,是原始OpenCL API的1:1映射
http://jcuda.org/:CUDA的Java绑定:低级绑定,是原始CUDA API的1:1映射
杂