Анализ производительности суммирования рядов в Matlab - PullRequest
0 голосов
/ 21 января 2019

Я пишу программу 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-axis и правильно сослался на команду polyfit.

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Есть несколько вещей, которые можно улучшить в вашем коде:

  • f должно быть предварительно выделено, чтобы не тратить время на повторное выделение памяти.
  • tic должен вызываться в цикле, чтобы перезапустить таймер секундомера.
  • Когда вы звоните toc, вы получаете текущее время от последнего tic.Затраченное время должно быть сохранено в векторе (также предварительно выделенном).
  • Поскольку вычисления, которые вы хотите рассчитать, очень быстрые, измерение времени, которое они занимают, очень нереально.Расчеты следует повторять много раз, поэтому измеренное время будет больше, и вы получите лучшую точность.Еще лучше было бы использовать 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);

Использование timeit для измерения времени, вероятно, даст улучшенную точность (но не очень хорошую, потому что,как уже упоминалось выше, вычисления, которые вы хотите рассчитать, очень быстрые).Чтобы использовать timeit, вам нужно определить функцию с кодом для синхронизации.Самый простой способ - использовать анонимную функцию без входных аргументов.Смотрите код ниже.

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);
0 голосов
/ 21 января 2019

Если я правильно понимаю вашу проблему, я думаю, что здесь есть две разные проблемы. Сначала вы выводите на экран свою функцию результата, а затем истекшее время, которое на несколько порядков меньше, чем 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 для наклона времени выполнения. Это помогает?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...