我正在使用Boost UBlas的数字库绑定来解决一个简单的线性系统。 以下工作正常,但它仅限于相对处理矩阵A(m x m) 小'''。
在实践中,我有一个更大的矩阵,维数m = 10 ^ 6(最多10 ^ 7) 是否存在用于解决有效使用内存的Ax = b的现有C ++方法。
#include<boost/numeric/ublas/matrix.hpp>
#include<boost/numeric/ublas/io.hpp>
#include<boost/numeric/bindings/traits/ublas_matrix.hpp>
#include<boost/numeric/bindings/lapack/gesv.hpp>
#include <boost/numeric/bindings/traits/ublas_vector2.hpp>
// compileable with this command
//g++ -I/home/foolb/.boost/include/boost-1_38 -I/home/foolb/.boostnumbind/include/boost-numeric-bindings solve_Axb_byhand.cc -o solve_Axb_byhand -llapack
namespace ublas = boost::numeric::ublas;
namespace lapack= boost::numeric::bindings::lapack;
int main()
{
ublas::matrix<float,ublas::column_major> A(3,3);
ublas::vector<float> b(3);
for(unsigned i=0;i < A.size1();i++)
for(unsigned j =0;j < A.size2();j++)
{
std::cout << "enter element "<<i << j << std::endl;
std::cin >> A(i,j);
}
std::cout << A << std::endl;
b(0) = 21; b(1) = 1; b(2) = 17;
lapack::gesv(A,b);
std::cout << b << std::endl;
return 0;
}
答案 0 :(得分:14)
简短回答:不要使用Boost的LAPACK
绑定,这些绑定是为密集矩阵设计的,
不是稀疏矩阵,而是使用UMFPACK
。
答案很长:当{A很大且稀疏时,UMFPACK
是解决Ax = b的最佳库之一。
以下是生成简单umfpack_simple.c
和A
的示例代码(基于b
)
并解决Ax = b
。
#include <stdlib.h>
#include <stdio.h>
#include "umfpack.h"
int *Ap;
int *Ai;
double *Ax;
double *b;
double *x;
/* Generates a sparse matrix problem:
A is n x n tridiagonal matrix
A(i,i-1) = -1;
A(i,i) = 3;
A(i,i+1) = -1;
*/
void generate_sparse_matrix_problem(int n){
int i; /* row index */
int nz; /* nonzero index */
int nnz = 2 + 3*(n-2) + 2; /* number of nonzeros*/
int *Ti; /* row indices */
int *Tj; /* col indices */
double *Tx; /* values */
/* Allocate memory for triplet form */
Ti = malloc(sizeof(int)*nnz);
Tj = malloc(sizeof(int)*nnz);
Tx = malloc(sizeof(double)*nnz);
/* Allocate memory for compressed sparse column form */
Ap = malloc(sizeof(int)*(n+1));
Ai = malloc(sizeof(int)*nnz);
Ax = malloc(sizeof(double)*nnz);
/* Allocate memory for rhs and solution vector */
x = malloc(sizeof(double)*n);
b = malloc(sizeof(double)*n);
/* Construct the matrix A*/
nz = 0;
for (i = 0; i < n; i++){
if (i > 0){
Ti[nz] = i;
Tj[nz] = i-1;
Tx[nz] = -1;
nz++;
}
Ti[nz] = i;
Tj[nz] = i;
Tx[nz] = 3;
nz++;
if (i < n-1){
Ti[nz] = i;
Tj[nz] = i+1;
Tx[nz] = -1;
nz++;
}
b[i] = 0;
}
b[0] = 21; b[1] = 1; b[2] = 17;
/* Convert Triplet to Compressed Sparse Column format */
(void) umfpack_di_triplet_to_col(n,n,nnz,Ti,Tj,Tx,Ap,Ai,Ax,NULL);
/* free triplet format */
free(Ti); free(Tj); free(Tx);
}
int main (void)
{
double *null = (double *) NULL ;
int i, n;
void *Symbolic, *Numeric ;
n = 500000;
generate_sparse_matrix_problem(n);
(void) umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, null, null);
(void) umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null);
umfpack_di_free_symbolic (&Symbolic);
(void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, null, null);
umfpack_di_free_numeric (&Numeric);
for (i = 0 ; i < 10 ; i++) printf ("x [%d] = %g\n", i, x [i]);
free(b); free(x); free(Ax); free(Ai); free(Ap);
return (0);
}
函数generate_sparse_matrix_problem
创建矩阵A
和
右侧b
。矩阵首先以三重形式构建。该
向量Ti,Tj和Tx完全描述A.三胞胎形式很容易创建但是
有效的稀疏矩阵方法需要压缩稀疏列格式。转变
使用umfpack_di_triplet_to_col
执行。
使用umfpack_di_symbolic
执行符号分解。稀疏
使用A
执行umfpack_di_numeric
的LU分解。
使用umfpack_di_solve
执行下三角和上三角解算。
n
为500,000,在我的机器上,整个程序需要大约一秒钟才能运行。
Valgrind报告分配了369,239,649字节(仅略高于352 MB)。
请注意,此page讨论了Boost对Triplet(坐标)中稀疏矩阵的支持
和压缩格式。如果您愿意,可以编写例程来转换这些boost对象
简单数组UMFPACK
需要输入。
答案 1 :(得分:6)
假设你的巨大矩阵是稀疏的,我希望它们是那么大,看看PARDISO项目是一个稀疏线性求解器,如果你想处理矩阵,这就是你需要的就像你说的那么大。允许有效存储非零值,并且比解决相同的密集矩阵系统快得多。
答案 2 :(得分:6)
我认为你的矩阵是密集的。如果它是稀疏的,您可以找到许多专门的算法,如DeusAduro和duffymo所述。
如果您没有足够大的(足够大的)群集,那么您需要查看核心外算法。 ScaLAPACK prototype package有一些核心外解决方案作为其here的一部分,请参阅文档Google和here以获取更多详细信息。在网上搜索“核外LU /(矩阵)求解器/包”将为您提供大量其他算法和工具的链接。我不是那些专家。
对于这个问题,大多数人会使用群集。您将在几乎任何群集上找到的包再次是ScaLAPACK。此外,典型群集上通常还有许多其他软件包,因此您可以选择适合您问题的软件包(示例here和{{3}})。
在开始编码之前,您可能希望快速检查解决问题所需的时间。典型的求解器需要大约O(3 * N ^ 3)个触发器(N是矩阵的维数)。如果N = 100000,那么您将看到3000000 Gflops。假设您的内存中求解器每个核心的速度为10 Gflops / s,那么您在单个核心上看到的是3 1/2天。由于算法可以很好地扩展,因此增加内核数量可以减少接近线性的时间。最重要的是I / O.
答案 3 :(得分:3)
不确定C ++实现,但如果内存是一个问题,你可以做几件事,具体取决于你正在处理的矩阵类型:
答案 4 :(得分:3)
看看由Jack Dongarra和Hatem Ltaief编辑的list of freely available software for the solution of linear algebra problems。
我认为对于你正在研究的问题规模,你可能需要一个迭代算法。如果您不想以稀疏格式存储矩阵A,则可以使用无矩阵实现。迭代算法通常不需要访问矩阵A的各个条目,它们仅需要计算矩阵向量乘积Av(有时是A ^ T v,转置矩阵与向量的乘积)。因此,如果库设计得很好,那么如果你传授一个知道如何制作矩阵矢量产品的类就足够了。
答案 5 :(得分:1)
由于接受的答案表明存在UMFPACK。但是如果你使用BOOST,你仍然可以在BOOST中使用紧凑矩阵并使用UMFPACK来解决系统问题。有一个绑定,使它很容易:
http://mathema.tician.de/software/boost-numeric-bindings
它大约两年了,但它只是一个约束力(以及其他一些)。