Числовая оценка пи Используя передачу сообщений

Этот пример показывает основы работы с spmd операторами, и как они обеспечивают интерактивные средние значения выполнения параллельных расчетов. Мы делаем это путем выполнения относительно простых расчетов, чтобы аппроксимировать пи.

Связанная документация:

  • spmd в руководстве пользователя Parallel Computing Toolbox™

Связанные примеры:

Код, показанный в этом примере, может быть найден в этой функции:

function paralleldemo_quadpi_mpi

Введение

Мы намереваемся использовать факт это

$$ \int_0^1 {4 \over {1 + x^2}} dx = 4(atan(1) - atan(0)) = \pi$$

аппроксимировать пи путем аппроксимации интеграла слева.

Мы намереваемся иметь параллельный пул, выполняют вычисления параллельно, и использовать spmd ключевое слово, чтобы отметить параллельные блоки кода. Мы сначала смотрим на размер параллельного пула, который в настоящее время открыт.

p = gcp;
p.NumWorkers
ans =

    12

Параллелизируйте расчеты

Мы аппроксимируем пи числовым интегралом 4/(1 + x^2) от 0 до 1.

type pctdemo_aux_quadpi.m
function y = pctdemo_aux_quadpi(x)
%PCTDEMO_AUX_QUADPI Return data to approximate pi.
%   Helper function used to approximate pi.  This is the derivative 
%   of 4*atan(x).

%   Copyright 2008 The MathWorks, Inc.
y = 4./(1 + x.^2);

Мы делимся, работа между рабочими (лаборатории) при наличии каждого рабочего вычисляют интеграл функции на подынтервале [0, 1] как показано в изображении.

Мы задаем переменные a и b на всех рабочих, но позволяют их значениям зависеть от labindex так, чтобы интервалы [a, b] соответствовали показанным на рисунке подынтервалам. Мы затем проверяем, что интервалы правильны. Обратите внимание на то, что код в теле spmd оператора выполнен параллельно на всех рабочих в параллельном пуле.

spmd
    a = (labindex - 1)/numlabs;
    b = labindex/numlabs;
    fprintf('Subinterval: [%-4g, %-4g]\n', a, b);
end
Lab  1: 
  Subinterval: [0   , 0.0833333]
Lab  2: 
  Subinterval: [0.0833333, 0.166667]
Lab  3: 
  Subinterval: [0.166667, 0.25]
Lab  4: 
  Subinterval: [0.25, 0.333333]
Lab  5: 
  Subinterval: [0.333333, 0.416667]
Lab  6: 
  Subinterval: [0.416667, 0.5 ]
Lab  7: 
  Subinterval: [0.5 , 0.583333]
Lab  8: 
  Subinterval: [0.583333, 0.666667]
Lab  9: 
  Subinterval: [0.666667, 0.75]
Lab 10: 
  Subinterval: [0.75, 0.833333]
Lab 11: 
  Subinterval: [0.833333, 0.916667]
Lab 12: 
  Subinterval: [0.916667, 1   ]

Мы позволяем всем рабочим теперь использовать квадратурный метод MATLAB, чтобы аппроксимировать каждый интеграл. Они все работают с той же функцией, но с различными подынтервалами [0,1] показанный на рисунке выше.

spmd
    myIntegral = integral(@pctdemo_aux_quadpi, a, b);
    fprintf('Subinterval: [%-4g, %-4g]   Integral: %4g\n', ...
            a, b, myIntegral);
end
Lab  1: 
  Subinterval: [0   , 0.0833333]   Integral: 0.332565
Lab  2: 
  Subinterval: [0.0833333, 0.166667]   Integral: 0.32803
Lab  3: 
  Subinterval: [0.166667, 0.25]   Integral: 0.31932
Lab  4: 
  Subinterval: [0.25, 0.333333]   Integral: 0.307088
Lab  5: 
  Subinterval: [0.333333, 0.416667]   Integral: 0.292162
Lab  6: 
  Subinterval: [0.416667, 0.5 ]   Integral: 0.275426
Lab  7: 
  Subinterval: [0.5 , 0.583333]   Integral: 0.257707
Lab  8: 
  Subinterval: [0.583333, 0.666667]   Integral: 0.239713
Lab  9: 
  Subinterval: [0.666667, 0.75]   Integral: 0.221994
Lab 10: 
  Subinterval: [0.75, 0.833333]   Integral: 0.204949
Lab 11: 
  Subinterval: [0.833333, 0.916667]   Integral: 0.188836
Lab 12: 
  Subinterval: [0.916667, 1   ]   Integral: 0.173804

Добавьте результаты

Рабочие все вычислили свои фрагменты интеграла функции, и мы добавляем результаты вместе, чтобы сформировать целый интеграл по [0, 1]. Мы используем gplus функция, чтобы добавить myIntegral через всех рабочих и возвращают сумму на всех рабочих.

spmd
    piApprox = gplus(myIntegral);
end

Смотрите результаты в клиенте

Начиная с переменной piApprox был присвоен внутренней части spmd оператор, это доступно на клиенте как Составной объект. Составные объекты напоминают массивы ячеек с одним элементом для каждого рабочего. Индексация в Составной объект возвращает соответствующее значение от рабочего клиенту.

approx1 = piApprox{1};   % 1st element holds value on worker 1.
fprintf('pi           : %.18f\n', pi);
fprintf('Approximation: %.18f\n', approx1);
fprintf('Error        : %g\n', abs(pi - approx1))
pi           : 3.141592653589793100
Approximation: 3.141592653589792700
Error        : 4.44089e-16