如果这很明显,很抱歉,但我搜索了一段时间,没有找到任何东西(或错过了它)。
我试图求解形式为Ax=B的线性系统,其中A为4x4矩阵,B为4x1向量。
我知道对于单个系统,我可以使用mldivide
来获得x:x=AB
。
然而,我正在尝试解决大量系统(可能>10000),我不愿意使用for循环,因为我被告知在许多MATLAB问题中,它明显比矩阵公式慢。
那么,我的问题是:有没有一种方法可以使用向量化来解决Ax=B,其中a4xN和B矩阵4xN PS:我不知道这是否重要,但B向量对所有系统都是相同的。
您应该使用for循环。如果A
保持不变并且B
发生变化,那么预计算因子分解并重用它可能会有好处。但对于A
发生变化而B
保持不变的问题,除了求解N个线性系统外,别无选择。
你也不应该太担心循环的性能成本:MATLAB JIT编译器意味着循环在最新版本的MATLAB上通常可以同样快。
我认为您无法对此进行进一步优化。正如@Tom所解释的,由于A
是一个变化的,因此事先将各种A
分解是没有好处的。。。
此外,考虑到你提到的尺寸,环形解决方案非常快:
A = rand(4,4,10000);
B = rand(4,1); %# same for all linear systems
tic
X = zeros(4,size(A,3));
for i=1:size(A,3)
X(:,i) = A(:,:,i)B;
end
toc
运行时间为0.168101秒。
问题如下:您正在尝试对三维矩阵执行二维运算(mldive)。无论你怎么看,你都需要通过索引来参考矩阵,这就是时间点球的位置……问题不是for循环,而是人们如何使用它们。如果你能以不同的方式构建你的问题,那么也许你可以找到更好的选择,但现在你有几个选择:
1-mex
2-并行处理(写一个parfor循环)
3-CUDA
这里有一个相当深奥的解决方案,它利用了MATLAB的特殊优化。用对角线上的4x4块构建一个巨大的4k x 4k稀疏矩阵。然后同时解决所有问题。
在我的机器上,这得到了与@Amro/Tom的循环解决方案相同的解决方案,高达单精度精度,但速度更快。
n = size(A,1);
k = size(A,3);
AS = reshape(permute(A,[1 3 2]),n*k,n);
S = sparse( ...
repmat(1:n*k,n,1)', ...
bsxfun(@plus,reshape(repmat(1:n:n*k,n,1),[],1),0:n-1), ...
AS, ...
n*k,n*k);
X = reshape(Srepmat(B,k,1),n,k);
例如:
For k = 10000
For loop: 0.122570 seconds.
Giant sparse system: 0.032287 seconds.
如果你知道你的4x4矩阵是正定的,那么你可以在S上使用chol
来提高精度。
这太傻了。但在2015年,即使使用JIT,matlab的循环速度也是如此。当k不太大时,这个解决方案似乎找到了一个最佳点,这样所有东西都能进入内存。
我知道这篇文章已经有几年的历史了,但无论如何我都会贡献我的两分钱。你可以把所有的A矩阵放在一个更大的块对角矩阵中,在一个大矩阵的对角线上会有4x4个块。右手边将是所有的b向量一个接一个地堆叠在一起。一旦你设置了这个,它就被表示为一个稀疏系统,并且可以用mldive选择的算法有效地求解。这些块在数字上是解耦的,所以即使其中有奇异块,当你使用mldivide时,非奇异块的答案也应该是正确的。MATLAB Central上有一个代码采用了这种方法:
http://www.mathworks.com/matlabcentral/fileexchange/24260-multiple-same-size-linear-solver
我建议进行试验,看看这种方法是否比循环更快。我怀疑它可以更高效,尤其是对于大量的小型系统。特别是,如果有N个矩阵中A系数的好公式,你可以使用MATLAB向量运算(无循环)构建完整的左手边,这可以为你节省额外的成本。正如其他人所指出的,矢量化操作并不总是更快,但根据我的经验,它们往往更快。