我有一个做线性代数的Java程序。我使用jblas库,根据我的理解,它应该调用实现Blas和Lapack的本机库,以获得更快的结果。
此代码在Docker中运行,并在AWS批处理管理的作业中启动。
摘自Dockerfile:
FROM debian:stretch
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get -y install libgfortran3 # install fortran
RUN apt-get -y install openjdk-8-jdk # install java 8
我尝试提高速度来逆24000 × 24000平方对称矩阵。我看到jblas库提供了2种方法。一种是使用本地dgesv进行通用线性系统求解过程和另一个使用本机dsysv求解对称矩阵的过程
程序。DoubleMatrix A = ...; // my 24k symmetric square matrix
DoubleMatrix B = DoubleMatrix.eye(A.rows);// Identity matrix
DoubleMatrix C = Solve.solve(A, B);// takes 4020 s
DoubleMatrix D = Solve.solveSymmetric(A, B);// takes 5040 s, longer than the calculation of C
问题1:当应该使用本地Blas和Lapack库时,解决24k平方矩阵需要花费这么多时间是正常的吗?如果没有,如何在运行AWS批处理作业时提高速度?
问题2:为什么对称解(dsysv)比一般解(dgesv)慢?我的期望是,如果我们让本机库知道输入矩阵是对称的,它会给它一个提示,使它能够更快地求解线性系统。
顺便说一下,我检查了这两种方法是否会得到相同的数值结果。
我只回答一个问题。
- 解决一个24k平方矩阵需要这么多时间是正常的吗?A:是的,矩阵反转是O(n^3),所以你要做几十万亿次的操作。你用矩阵逆来做什么?如果你只是想解决一个系统,那么最好使用类似于神经网络中流行的梯度下降方法的迭代算法,例如Gauss-Seidel或Richardson。
另一个问题很棘手,并非对称矩阵中的所有操作都比一般矩阵中的操作更有效。为了便于讨论,假设你想要一个列主一维数组形式的一般矩阵中的单个元素。A[i,j] = A_ge[j*N+i]
,但在对称表示中,下三角形部分A[i,j] = i > j ? A_sy[i*(i+1)/2 + j] : A_sy[j*(j+1)/2 + i]
,内存中的冗余使检索所需元素变得更简单。
我认为如果实现了最有效的算法,答案应该是否定的。但是使用对称矩阵表示的主要动机可能是为了节省内存或数值稳定性,而不是速度。
运行时增加20%可能是由于索引效率较低,例如