为什么这个椭圆绘图程序这么慢?

时间:2019-04-26 19:53:26

标签: drawing octave ellipse

我有一个程序来绘制具有均匀相位分布的椭圆形网格。但是,它非常慢。

我希望我的代码更快,以便可以使用N = 150M = 150。 如何加快此代码的速度?

N = 10;
M = 10;
y = 1;
x = 1;
a = 1;
b = 2;
for k = 1:N
  for m = 1:N
    w = rand(1,1);
    for l = 1:N
      for s = 1:N
        if(((l-x)*cos(w*pi)+(s-y)*sin(w*pi)).^2/a^2 + (-(l-x)*sin(w*pi) + (s-y)*cos(w*pi)).^2/b.^2 <= 1)
          f(l,s) = 1*(cos(0.001)+i*sin(0.001));
        end
      end
    end
    y = y+4;
  end
  y = 1;
  x = x+5;
end
image(arg(f),'CDataMapping','scaled');

这是代码产生的:

Picture

已更新:

N = 10;
M = 10;
y = 1;
x = 1;
a = 1;
b = 2;
for x = 1:5:N
  for y = 1:4:N
    w = rand(1);
    for l = 1:N
      for s = 1:N
        if(((l-x).*cos(w.*pi)+(s-y).*sin(w.*pi)).^2/a.^2 + (-(l-x).*sin(w.*pi) + (s-y).*cos(w.*pi)).^2/b.^2 <= 1)
          f(l,s) = cos(0.001)+i.*sin(0.001);
        end
      end
    end
  end
  y = 1;
end
image(arg(f),'CDataMapping','scaled');

2 个答案:

答案 0 :(得分:1)

您可以执行许多操作来加快计算速度。一个重要的问题是删除循环,并用矢量化代码替换它们。一次执行多次计算时,Octave的运行速度要快得多,而不是一次执行一次。

例如,代替

for l = 1:N
  for s = 1:N
    if(((l-x).*cos(w.*pi)+(s-y).*sin(w.*pi)).^2/a.^2 + (-(l-x).*sin(w.*pi) + (s-y).*cos(w.*pi)).^2/b.^2 <= 1)
      f(l,s) = cos(0.001)+i.*sin(0.001);
    end
  end
end

一个人可以写

l = 1:N;
s = (1:N).';
index = ((l-x).*cos(w.*pi)+(s-y).*sin(w.*pi)).^2/a.^2 + (-(l-x).*sin(w.*pi) + (s-y).*cos(w.*pi)).^2/b.^2 <= 1;
f(index) = cos(0.001)+i.*sin(0.001);

但是,这里我们仍然做很多工作,因为我们在已知会超出椭圆扩展的位置上计算index。理想情况下,我们会在知道椭圆适合的每个点(x,y)周围找到一个较小的区域。

要做的另一件事是预先分配数组。 f在循环迭代中增长。相反,应该在循环开始之前使用最终大小创建f

还进行了许多冗余计算。例如,w.*pi被多次计算,其中的cossin也被计算。您还分配cos(0.001)+i.*sin(0.001)一遍又一遍地输出像素,这可以是一次计算的常数。

以下代码在MATLAB中运行的时间仅为一秒钟(尽管Octave会慢很多)。我还正确地分离了NM(因此输出并不总是正方形的),并且将步长设置为变量,以提高对代码的理解。我为椭圆元素分配了1,您可以通过将f = f * (cos(0.001)+i*sin(0.001))乘以常量来替换它们。

N = 150;
M = 200;
a = 5;
b = 10;
x_step = 25;
y_step = 25;
f = zeros(N,M);
for x = x_step/2:x_step:M
  for y = y_step/2:y_step:N
    phi = rand(1)*pi;
    cosphi = cos(phi);
    sinphi = sin(phi);
    l = (1:M)-x;
    s = (1:N).'-y;
    index = (l*cosphi+s*sinphi).^2/a.^2 + (-l*sinphi + s*cosphi).^2/b.^2 <= 1;
    f(index) = 1;
  end
end

output of algorithm

答案 1 :(得分:0)

我不确定您要尝试做什么。请参阅下面的代码,让我知道。运行150 x 150的箱子大约花了30秒钟。不确定速度是否足够

[h,k] = meshgrid(0:150, 0:150);

a = 0.25;
b = 0.5;

phi = reshape( linspace( 0 , 2*pi , numel(h) ), size(h));

theta = linspace(0,2*pi,50)';

x = a*cos(theta);
y = b*sin(theta);

h = h(:);
k = k(:);
phi = phi(:);

ellipseX = arrayfun(@(H,K,F) x*cos(F)-y*sin(F) + H , h,k,phi, 'uni', 0);
ellipseY = arrayfun(@(H,K,F) x*sin(F)+y*cos(F) + K , h,k,phi, 'uni', 0);

ellipse = [ellipseX, ellipseY, repmat({'r'}, size(ellipseX))]';

fill(ellipse{:})