用于GMRES中用于C或C ++中的大矩阵的矩阵向量积的更快方法

时间:2013-11-01 02:25:15

标签: c++ c matlab matrix matrix-multiplication

我有一个大的,密集的矩阵A,我的目标是使用迭代方法找到线性系统Ax = b的解(在MATLAB中是使用其内置GMRES的计划)。对于超过10,000行,这对于我的计算机存储在内存中来说太多了,但我知道A中的条目由两个长度为N的已知向量x和y构成,条目满足: A(i,j)= .5 *(x [i] -x [j])^ 2 +([y [i] -y [j])^ 2 * log(x [i] -x [j] )^ 2 +([Y [I] -y [J] ^ 2)。

MATLAB的GMRES命令接受一个函数调用作为输入,该函数调用可以计算矩阵向量乘积A * x,这使我能够处理比存储在内存中的矩阵更大的矩阵。为了编写matrix-vecotr产品函数,我首先在matlab中尝试逐行并使用一些向量化,但我避免产生整个数组A(因为它太大了)。在我的GMRES申请中,这是相当缓慢的。我的计划是为MATLAB编写一个mex文件,它在C中,理想情况下应该比matlab代码快得多。我对C很新,所以这个问题相当糟糕,我在C语言中编写代码的天真尝试比在Matlab中部分向量化的尝试要慢。

#include <math.h>
#include "mex.h"
void Aproduct(double *x, double *ctrs_x, double *ctrs_y, double *b, mwSize n)
{
    mwSize i;
    mwSize j;
    double val;
    for (i=0; i<n; i++) {
        for (j=0; j<i; j++) {
            val = pow(ctrs_x[i]-ctrs_x[j],2)+pow(ctrs_y[i]-ctrs_y[j],2);

            b[i] = b[i] + .5* val * log(val) * x[j];
        }
        for (j=i+1; j<n; j++) {
            val = pow(ctrs_x[i]-ctrs_x[j],2)+pow(ctrs_y[i]-ctrs_y[j],2);

            b[i] = b[i] + .5* val * log(val) * x[j];
        }
    }
}

以上是matlab mex文件代码的计算部分(如果我理解正确的话,稍微修改一下C)。请注意,我跳过i = j的情况,因为在这种情况下变量val将是0 * log(0),对我来说应该被解释为0,所以我只是跳过它。

有更高效或更快的方式来写这个吗?当我通过matlab中的mex文件调用这个C函数时,它比我使用的matlab方法慢得多,速度慢。这让我感到惊讶,因为我怀疑C代码应该比matlab快得多。

我正在比较它的部分矢量化的替代matlab方法是

function Ax = Aprod(x,ctrs)
n = length(x);
Ax = zeros(n,1);
for j=1:(n-3)
    v = .5*((ctrs(j,1)-ctrs(:,1)).^2+(ctrs(j,2)-ctrs(:,2)).^2).*log((ctrs(j,1)-ctrs(:,1)).^2+(ctrs(j,2)-ctrs(:,2)).^2);

    v(j)=0;
    Ax(j) = dot(v,x(1:n-3);
end

(n-3是因为实际上有3个额外的组件,但它们是分开处理的,所以我排除了那个代码)。这部分是矢量化的,只需要一个for循环,所以它更有意义。但是,我希望我能用C + mex文件更快。

任何建议或帮助将不胜感激!谢谢!

编辑:我应该更清楚。我对任何可以帮助我使用GMRES反转我感兴趣的矩阵的更快的方法持开放态度,这需要更快的方式来执行矩阵向量产品而无需将数组显式加载到内存中。谢谢!

1 个答案:

答案 0 :(得分:1)

如果您有Parallel Computing ToolboxMATLAB Distributed Computing Server,则可以直接使用反斜杠解决大型密集线性系统。 (如果您没有可用的群集,则可能希望使用Amazon EC2 machines)。像这样:http://www.mathworks.co.uk/help/distcomp/examples/benchmarking-a-b.html