代码之家  ›  专栏  ›  技术社区  ›  Axion004

matlab中级数求和的性能分析

  •  1
  • Axion004  · 技术社区  · 7 年前

    我正在编写一个matlab程序,通过级数求和来计算π

    A = Sum of a_i from i=1 to N
    

    哪里

    pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + 1/13 ...
    

    为了通过级数求和计算π,建议的方法是

    a_i = (-1)^(i+1)/(2i-1)
    

    为了做到这一点,我编写了下面的程序

    n=100;
    f=[];
    for jj=1:n
        ii=1:jj;
        f=[f 4*sum( ((-1).^(ii+1))./(2.*ii-1)  )];
    end;
    hold on
    plot(f)
    title('Computing of \pi using a finite sum')
    xlabel('Number of summations') 
    ylabel('Estimated value of \pi') 
    plot(1:size(f,2),ones(size(f))*pi)
    

    这个程序表明,级数近似在近似的情况下是有点精确的。 N=80 .

    enter image description here

    我现在正在尝试调整我的程序,以便 y-axis displays total calculation time T_N 以及 x-axis displays N (the number of summations) . 总计算时间t_n应随着n的增加而增加。理想情况下,我希望让图表显示的内容与 T(N) N

    enter image description here

    为此,我对原始程序进行了如下调整

    n=100;
    f=[];
    tic
    for jj=1:n
        ii=1:jj;
        f=[f 4*sum( ((-1).^(ii+1))./(2.*ii-1)  )];
    end;
    hold on
    plot(f)
    title('Time it takes to sum \pi using N summations')
    xlabel('Number of summations (N)') 
    ylabel('Total Time (T_N)') 
    plot(1:size(f,2),toc)
    slope = polyfit(1:size(f,2),toc,1);
    

    enter image description here

    这看起来不对。我一定是在matlab(tic和toc)中错误地应用了内置的计时函数。所以,我要分析我的代码并问两个问题-

    1. 如何调整上面的代码,使Y轴正确显示每个求和n的总计算时间?我好像做错了什么 plot(1:size(f,2),toc) .

    2. 在我得到 y-axis 显示正确的 total calculation time (T_N) ,我应该可以使用 polyfit 用于查找坡度的命令 T(N)/N . 这将给我一个线性关系 T(N) and N . 然后我可以使用 slope = polyfit(1:size(f,2),toc,1) 计算

      t_N = a + b*N

    哪里 t_N 为每个值计算 n b 是通过polyfit命令计算的坡度。

    我想我应该能找到 values of a and b 在我正确显示 Y轴 并正确引用polyfit命令。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Morc    7 年前

    如果我正确理解你的问题,我认为这里有两个不同的问题。首先,绘制结果函数,然后绘制比pi小几个数量级的经过时间:

     hold on
     plot(f)  % <---- Comment me out!
     ...stuff...
     plot(1:size(f,2),toc)
    

    其次,您需要存储循环的每个过程的执行时间:

    n=100;
    f=[];
    telapsed = zeros(1,n);
    tic
    for jj=1:n
        ii=1:jj;
        f=[f 4*sum( ((-1).^(ii+1))./(2.*ii-1)  )];
        telapsed(jj) = toc;
    end
    hold on
    % plot(f)
    title('Time it takes to sum \pi using N summations')
    xlabel('Number of summations (N)') 
    ylabel('Total Time (T_N)') 
    plot(1:n,telapsed)
    slope = polyfit(1:n,telapsed,1);
    

    注意新的polyfit表达式用于执行时间的坡度。这有帮助吗?

        2
  •  3
  •   Luis Mendo    7 年前

    代码中有几个方面可以改进:

    • f 应预先分配,以免在重复分配内存时浪费时间。
    • tic 应该在循环内调用,以便重新启动秒表计时器。
    • 当你打电话 toc 你得到了 现在的 从上次开始的时间 抽搐 . 所花费的时间应该存储在一个向量中(也应该是预分配的)。
    • 由于你想计算时间非常快,测量他们所花费的时间是非常不现实的。计算应该重复很多次,所以测量的时间更大,而且精度更好。更好的方法是使用 timeit (见下文)。
    • 您不能在同一个图中绘制时间和结果,因为比例太不同了。

    包含这些变更的代码是:

    n = 100;
    f = NaN(1,n); % preallocate
    times = NaN(1,n); % preallocate
    repeat_factor = 1e4; % repeat computations for better time accuracy
    for jj=1:n
        tic % initiallize time count
        for repeat = 1:repeat_factor % repeat many times for better time accuracy
            ii=1:jj;
            f(jj) = 4*sum( ((-1).^(ii+1))./(2.*ii-1) ); % store value
        end
        times(jj) = toc; % store time
    end
    times = times / repeat_factor; % divide by repeat factor
    plot(f)
    title('Time it takes to sum \pi using N summations')
    xlabel('Number of summations (N)') 
    ylabel('Total Time (T_N)')
    figure % new figure for time
    plot(1:size(f,2), times)
    p = polyfit(1:size(f,2),times,1);
    slope = p(1);
    

    使用 时计 因为测量时间可能会提高精度(但不是很好,因为如上所述,您想要的计算时间非常快)。使用 时计 您需要用要计时的代码定义一个函数。最简单的方法是使用 anonymous function 没有输入参数。参见下面的代码。

    n = 100;
    f = NaN(1,n); % preallocate
    times = NaN(1,n); % preallocate
    for jj=1:n
        ii=1:jj;
        fun = @() 4*sum( ((-1).^(ii+1))./(2.*ii-1) );
        f(jj) = fun(); % store value
        times(jj) = timeit(fun); % measure and store time
    end
    plot(f)
    title('Time it takes to sum \pi using N summations')
    xlabel('Number of summations (N)') 
    ylabel('Total Time (T_N)')
    figure % new figure for time
    plot(1:size(f,2), times)
    p = polyfit(1:size(f,2),times,1);
    slope = p(1);