C++ C或C+中大矩阵向量积的快速算法+;用于GMRES

C++ C或C+中大矩阵向量积的快速算法+;用于GMRES,c++,c,matlab,matrix,matrix-multiplication,C++,C,Matlab,Matrix,Matrix Multiplication,我有一个大而密集的矩阵a,我的目标是用迭代法找到线性系统Ax=b的解(在MATLAB中是使用内置GMRES的计划)。对于超过10000行,我的计算机无法将其存储在内存中,但我知道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,这允许我处理比内存中存储

我有一个大而密集的矩阵a,我的目标是用迭代法找到线性系统Ax=b的解(在MATLAB中是使用内置GMRES的计划)。对于超过10000行,我的计算机无法将其存储在内存中,但我知道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,这允许我处理比内存中存储的矩阵更大的矩阵。为了编写矩阵向量积函数,我首先在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];
        }
    }
}
(n-3是因为实际上有3个额外的组件,但它们是单独处理的,所以我排除了该代码)。这是部分矢量化的,只需要一个for循环,因此速度更快是有一定道理的。不过,我希望使用C+mex文件可以更快

如果您有任何建议或帮助,我们将不胜感激!谢谢


编辑:我应该更清楚。我愿意接受任何更快的方法,可以帮助我使用GMRES反转我感兴趣的矩阵,这需要一种更快的方法来进行矩阵向量积,而无需将数组显式加载到内存中。谢谢!

如果您有,您可以直接使用反斜杠求解大型密集线性系统(如果没有可用的群集,则可能希望使用)。例如:

如果有和,则可以直接使用反斜杠求解大型密集线性系统。(如果没有可用的群集,则可能希望使用)。像这样:

你的C代码明显较慢的原因是因为MatLab使用的算法比你的幼稚算法复杂得多,而且因为他们利用对CPU缓存、SSE指令和其他低级内容的深入了解将其优化到最后一位。我知道,在MatLab中Ax的直接计算速度比我可以做任何事情,但这不是我感兴趣的。因为我无法将A全部加载到内存中,我无法直接计算Ax,所以我必须使用某种循环机制。有没有比我现在做的更好的方法的想法,无论是我尝试的C代码还是我发布的matlab代码?谢谢!我看到了你现在面临的挑战:Ge在
A*x
计算过程中动态生成矩阵,因为你不能将
A
保存在内存中。你的MATLAB代码是合理的,除非你应该将
x(1:n-3)
存储在一个变量中,这样你就不必一直将其取出。在你的C代码中,我建议不要对一个简单的正方形使用
pow
pow(x,2.0)如果我没记错的话,
x*x
慢。你也可以做
b[I]+=…
,但我不确定这是否会更快。另外,由于两个
j
循环的目的只是为了避免
j=I
你可以组合循环并跟随
b[I]-=…
i=j
。您的C代码明显较慢的原因是MatLab使用的算法比您幼稚的算法复杂得多,并且因为他们利用对CPU缓存、SSE指令和其他低级内容的深入了解将其优化到最后一位。我知道Ax的直接计算速度会更快r在matlab中比我能做的任何事情都多,但这不是我感兴趣的。因为我无法将A全部加载到内存中,我无法直接计算Ax,所以我必须使用某种循环机制。有没有比我现在做的更好的方法的想法,无论是我尝试的C代码还是我发布的matlab代码?谢谢!我看到了你的挑战您现在面临的问题:在
A*x
计算过程中动态生成矩阵,因为您无法将
A
保存在内存中。您的MATLAB代码是合理的,除非您应该存储
x(1:n-3)
在一个变量中,这样你就不必一直拉出它。在你的C代码中,我建议不要使用
pow
作为一个简单的正方形。
pow(x,2.0)
x*x
慢,如果我没记错的话。你也可以这样做
b[I]+=…
,但我不确定这是否会更快。另外,由于两个
j
循环的目的只是为了避免
j=I
,您可以组合这些循环,然后使用
b[I]-=…
I=j
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