使用jCUDA实现复杂矩阵的java操作
使用jCuda处理复数的最佳方法是什么?我应该使用cuComplex格式还是有其他解决方案(比如实数部分和虚数部分一个接一个的数组)?我非常欣赏使用这种计算的java代码示例
由于我的目的是使用GPU解决带有复数的大型线性方程组,所以我不想只附加到jCuda。使用GPU进行此类计算的替代方法有哪些
你可以在下面搜索框中键入要查询的问题!
使用jCuda处理复数的最佳方法是什么?我应该使用cuComplex格式还是有其他解决方案(比如实数部分和虚数部分一个接一个的数组)?我非常欣赏使用这种计算的java代码示例
由于我的目的是使用GPU解决带有复数的大型线性方程组,所以我不想只附加到jCuda。使用GPU进行此类计算的替代方法有哪些
# 1 楼答案
首先,关于你关于在GPU上用Java进行计算的问题,我写了几句关于这个here
你的申请案例似乎非常具体。您可能应该更详细地描述您的实际意图,因为这将支配所有设计决策。到目前为止,我只能给出一些基本的提示。决定哪一个是最合适的解决方案取决于你
在Java世界和GPU世界之间架起桥梁的主要困难之一是内存处理的根本不同
C/C中的内存布局++
CUDA中的
cuComplex
结构定义为其中
float2
基本上是一个(带有一些额外的对齐规范等)
现在,当您在C/C++程序中分配一个
cuComplex
值数组时,您只需编写如下代码在这种情况下,保证所有这些
cuComplex
值的内存将是一个单个连续内存块。这个内存块只是由复数的所有x
和y
值组成,一个接一个:这个连续的内存块可以很容易地复制到设备上:一个获取指针,然后调用
Java中的内存布局
考虑创建一个结构上等于^ {CD1>}结构的java类的情况,并分配一个数组:
然后你没有一个
float
值的连续内存块。相反,您有一个引用到cuComplex
对象的数组,并且相应的x
和y
值分散在周围:这里的关键是:
无法将
cuComplex
对象的(Java)数组复制到设备上这有几个含义。在评论中,您已经提到了
cublasSetVector
方法,该方法将cuComplex
数组作为参数,我试图强调,这不是最有效的解决方案,只是为了方便起见。实际上,这种方法的工作原理是在内部创建一个新的ByteBuffer
以拥有一个连续的内存块,用cuComplex[]
数组中的值填充这个ByteBuffer
,然后将这个ByteBuffer
复制到设备上当然,这会增加开销,而在性能关键型应用程序中,您很可能希望避免这种开销
解决这个问题有几种选择。幸运的是,对于复数,解决方案相对简单:
不要使用
cuComplex
结构来表示复数数组相反,您应该将复数数组表示为单个连续内存块,其中复数的实部和虚部是交错的,每一部分分别是一个
float
或double
值。这将允许不同后端之间实现最大的互操作性(忽略某些细节,如对齐要求)不幸的是,这可能会造成一些不便,并提出一些问题,而且没有一个适合所有人的解决方案
如果我们试图概括这一点,不仅仅是指复数,而是指一般的“结构”,那么有一种“模式”可以应用:我们可以为结构创建接口,并创建这些结构的集合,即实现该接口的类的实例列表,它们都由一个连续的内存块支持。这可能适用于某些情况。但是对于复数,为每个复数拥有一个Java对象的内存开销可能会非常大
另一个极端是,仅处理原始
float[]
或double[]
数组也可能不是最佳解决方案。例如:如果您有一个表示c的float
值数组复数,那么你怎么能把一个复数和另一个复数相乘呢一个“中间”解决方案是创建一个接口,允许访问复数的实部和虚部。在实现中,这些复数存储在单个数组中,如上所述
我在这里画了这样一个实现
注:
这只是一个示例,展示基本思想,并展示它如何与JCublas这样的东西一起工作。对你来说,不同的策略可能更合适,这取决于你的实际目标:除了JCuda,还应该有哪些后端?在Java端处理复数应该有多“方便”?Java端处理复数的结构(类/接口)应该是什么样的
简而言之:在继续实现之前,您应该对应用程序/库应该能够做什么有一个非常清晰的概念
(顺便说一句:我可能会把这个答案的一部分扩展成样本和/或“如何……”页面为JCuda。提供此类信息的任务已经在我的“待办事项”清单上列出了很长一段时间)