[讨论]为啥去部分元素反而花费时间更长呢?

dlmaple
ph 07月13日 字数 461

下面是高斯消去法的一段代码,我觉得方法2可以减少部分运算,结果花费的时间比方法1还长一点点(生成1000节的方阵,然后测试a=rand(1000);

tic;guass(a);toc

注释掉方法2,取消注释方法1,然后再测试)每一次都是方法1时间短一点,而不是想象中的方法1耗费时间是方法2的二倍。

function a = guass(a)

for i=1:size(a,1)-1

for j=(i+1):size(a,1)

%a(j,:) = a(j,:) - a(j,i)/a(i,i)*a(i,:);   %方法1

a(j,i:end) = a(j,i:end) - a(j,i)/a(i,i)*a(i,i:end);  %方法2

end

end

end

MathTools 数学工具
13 个回复
zszqzzzf
炼狱天使——反者道之动 07月13日

凡是循环语句,基本上都可以优化为向量运算,速度提高10倍以上。

当然,程序员的水平是不一样的。

【 在 dlmaple (ph) 的大作中提到: 】

: 下面是高斯消去法的一段代码,我觉得方法2可以减少部分运算,结果花费的时间比方法1还长一点点(生成1000节的方阵,然后测试a=rand(1000);

: tic;guass(a);toc

: 注释掉方法2,取消注释方法1,然后再测试)每一次都是方法1时间短一点,而不是想象中的方法1耗费时间是方法2的二倍。

: ...................

dlmaple
ph 07月13日

你看我的帖子了吗?两个都是向量运算啊。当然,我知道有内置函数。

凡是循环语句,基本上都可以优化为向量运算,速度提高10倍以上。

当然,程序员的水平是不一样的。

【 在 dlmapl...

【 在 zszqzzzf 的大作中提到: 】

zszqzzzf
炼狱天使——反者道之动 07月13日

你不都有for循环吗?

想法干掉它们。

【 在 dlmaple (ph) 的大作中提到: 】

: 你看我的帖子了吗?两个都是向量运算啊。当然,我知道有内置函数。

: 凡是循环语句,基本上都可以优化为向量运算,速度提高10倍以上。

: 当然,程序员的水平是不一样的。

: ...................

dlmaple
ph 07月13日

谢谢,这里是个三重for循环,我把它变成了两重for(确实还可以再去掉一重,变成一个for循环,但不太可能完全去掉循环。)

我现在的疑问是为什么 a(:,n)=a(:,n)-a(m,n)/a(n,n)*a(:,m);

比   a(m:end,n)=a(m:end,n)-a(m,n)/a(n,n)*a(m:end,m)

速度快呢,毕竟第二种在很多情形下比第一种运算要少。

难道是语法糖m:end这里也需要一定的运算?

谢谢提醒,我把行运算改成列运算速度快了很多(方法1的时间是原来的1/13,fangfa2是原来的1/3)。

【 在 zszqzzzf 的大作中提到: 】

: 你不都有for循环吗?

: 想法干掉它们。

zszqzzzf
炼狱天使——反者道之动 07月15日

没有去除不了的for循环。

arrayfun等速度完全不一样。

【 在 dlmaple (ph) 的大作中提到: 】

: 谢谢,这里是个三重for循环,我把它变成了两重for(确实还可以再去掉一重,变成一个for循环,但不太可能完全去掉循环。)

: 我现在的疑问是为什么 a(:,n)=a(:,n)-a(m,n)/a(n,n)*a(:,m);

: 比   a(m:end,n)=a(m:end,n)-a(m,n)/a(n,n)*a(m:end,m)

: ...................

dlmaple
ph 07月15日

谢谢讨论。

我说两个事情:

1、你没仔细看我关注的点在哪儿。 我要修改 a(:,n)的元素,但因为前面部分没发生变化,所以我为了提高效率,只修改了a(m:end,n)这部分元素,但比修改 a(:,n)的所有元素还慢;

2、近几年版本里面循环的效率好像并不比所谓的向量化慢太多(你可以举一个五倍的例子),甚至更快了。 我举一个例子

>> tic;sum(1./(1:100000).^2);toc

历时 0.003972 秒。

>> tic;s=0;for i=1:100000,s=s+1/i^2;end;toc

历时 0.001462 秒。

这里可能涉及到开辟内存空间的缘故,数值比较大的时候所谓的向量化反而更慢了。在1000的时候也只有三倍的差距,并没有十几倍的差距。

【 在 zszqzzzf 的大作中提到: 】

: 没有去除不了的for循环。

: arrayfun等速度完全不一样。

zszqzzzf
炼狱天使——反者道之动 07月15日

一个个地修改向量中的元素,比起向量计算慢,这是已知的。

显然前者仅仅是后者的一部分。

但是计算次数不一样了。

【 在 dlmaple (ph) 的大作中提到: 】

: 谢谢讨论。

: 我说两个事情:

: 1、你没仔细看我关注的点在哪儿。 我要修改 a(:,n)的元素,但因为前面部分没发生变化,所以我为了提高效率,只修改了a(m:end,n)这部分元素,但比修改 a(:,n)的所有元素还慢;

: ...................

dlmaple
ph 07月15日

a(:,n)是一个向量,a(m:end,n)也是一个向量,而且后一个向量比前一个元素少,为啥后者慢那么多?

【 在 zszqzzzf 的大作中提到: 】

: 一个个地修改向量中的元素,比起向量计算慢,这是已知的。

: 显然前者仅仅是后者的一部分。

: 但是计算次数不一样了。

: ...................

templarsf
sf 07月16日

a=0;

fun_handle=[fun_a,fun_b.....fun_z];

for i=1:100

a=a+fun_handle{mod(a,26)}(a);

end

这个你来向量化一下.

【 在 zszqzzzf (炼狱天使——反者道之动) 的大作中提到: 】

: 没有去除不了的for循环。

: arrayfun等速度完全不一样。

zszqzzzf
炼狱天使——反者道之动 07月16日

你这是伪代码,跑不起来。

【 在 templarsf (sf) 的大作中提到: 】

: a=0;

: fun_handle=[fun_a,fun_b.....fun_z];

: for i=1:100

: ...................

wushunchao
fixer 07月17日

加重计算后,方法2就更快了,

比如把方法1中的"*a(i,:)"换成"*((a(:,i).^3).^(1/3))",方法2也类似换一下。

怀疑是生成a(i,i:end)时花了更多时间,只能猜,因为这没法像python可以看字节码。

【 在 dlmaple (ph) 的大作中提到: 】

: 下面是高斯消去法的一段代码,我觉得方法2可以减少部分运算,结果花费的时间比方法1还长一点点(生成1000节的方阵,然后测试a=rand(1000);

: tic;guass(a);toc

: 注释掉方法2,取消注释方法1,然后再测试)每一次都是方法1时间短一点,而不是想象中的方法1耗费时间是方法2的二倍。

: ...................

templarsf
sf 07月17日

大致意思就是每次执行的代码在这轮循环之前都不知道.

【 在 zszqzzzf (炼狱天使——反者道之动) 的大作中提到: 】

: 你这是伪代码,跑不起来。

zszqzzzf
炼狱天使——反者道之动 07月17日

优化是一门资深的技术活。

只为实际需要服务。

不是什么都能干的。

【 在 templarsf (sf) 的大作中提到: 】

: 大致意思就是每次执行的代码在这轮循环之前都不知道.