我有一个关于在Octave上运行SOR算法的学校项目,但我的效率非常低。所以我有这段代码:
for ii=1:n
r = 1/A(ii,ii);
for jj=1:n
if (ii!=jj)
A(ii,jj) = A(ii,jj)*r;
end;
end;
b(ii,1) = b(ii,1)*r;
x(ii,1) = b(ii,1);
end;
我该如何对此进行矢量化?我的第一次尝试是这样的:
for ii=1:n
r = 1/A(ii,ii);
A(find(eye(length(A))!=1)) = A(find(eye(length(A))!=1))*r;
b(ii,1) = b(ii,1)*r;
x(ii,1) = b(ii,1);
end;
但我不确定它有多大帮助。是否有更好和/或更有效的方法来做到这一点?
谢谢!
答案 0 :(得分:4)
你完全可以避免我认为的循环。你必须看到你作为A
的对角元素的倒数,那你为什么要使用循环。直接做。这是第一步。移除Inf
,现在您想将r
乘以相应行的相应非对角元素,对吗?
因此,使用repmat
构造这样一个矩阵,它将沿着列复制元素,因为你将r
乘以(1,2),(1,3),... ,(1,n)。但是R
具有非零对角线元素。因此,将它们归零。现在你将得到你的A,除了对角元素将为零。因此,您只需将其从原始A
添加回来。这可以通过A=A.*R+A.*eye(size(A,1))
来完成。
矢量化来自经验,最重要的是分析您的代码。想想在每一步是否要使用循环,如果没有用等效命令替换该步骤,其他代码将遵循(例如,我构造了一个矩阵R
,而你构建了单独的元素{{1}所以我只考虑转换r
- > r
,然后其余的代码就会到位。
代码如下:
R
答案 1 :(得分:2)
我想有矩阵:
A (NxN)
b (Nx1)
代码:
d = diag(A);
A = diag(1 ./ d) * A + diag(d - 1);
b = b ./ d;
x = b;
答案 2 :(得分:2)
随着问题被标记为vectorization
问题,随机地碰到了这个问题并且乍一看看起来很有趣。
我能够提出一个基于bsxfun
的矢量化解决方案,该解决方案也使用diagonal indexing
。这个解决方案似乎给我一个3-4x
加速循环代码加上适当大小的输入。
假设你仍然有兴趣看到这个问题的加速改进,我会急切地想知道你会得到的那种加速。这是代码 -
diag_ind = 1:size(A,1)+1:numel(A);
diag_A = A(diag_ind(:));
A = bsxfun(@rdivide,A,diag_A);
A(diag_ind) = diag_A;
b(:,1) = b(:,1)./diag_A;
x(:,1) = b(:,1);
让我知道!