В этом примере мы рассмотрим gop
функция и функции, которые на ней строятся: gplus
и gcat
. Эти, казалось бы, простые функции оказываются очень мощными инструментами при параллельном программировании.
The gop
функция позволяет нам выполнить любую ассоциативную двоичную операцию для переменной, которая задана во всех лабораториях. Это позволяет нам не только суммировать переменную по всем лабораториям, но и найти ее минимум и максимум по лабораториям, объединить их и выполнить много других полезных операций.
Сопутствующая документация:
spmd
в Руководстве пользователя Parallel Computing Toolbox™
Код, показанный в этом примере, можно найти в этой функции:
function paralleltutorial_gop
%#ok<*NOPRT>: disable code analyzer printing warning
При выполнении параллельного программирования мы часто сталкиваемся с ситуацией, когда переменная задана во всех лабораториях, и мы хотим выполнить операцию над переменной, поскольку она существует во всех лабораториях. Для примера, если мы вводим оператор spmd и задаем
spmd x = labindex end
Lab 1: x = 1 Lab 2: x = 2 Lab 3: x = 3 Lab 4: x = 4 Lab 5: x = 5 Lab 6: x = 6 Lab 7: x = 7 Lab 8: x = 8 Lab 9: x = 9 Lab 10: x = 10 Lab 11: x = 11 Lab 12: x = 12
во всех лабораториях, мы, возможно, захотим вычислить сумму значений x
через лаборатории. Это именно то, что gplus
операция делает, она суммирует x
в лабораториях и дублирует результат во всех лабораториях:
spmd s = gplus(x); end
Переменные, назначенные в операторе spmd, представлены на клиенте как Composite. Получившиеся значения из лабораторий мы можем принести клиенту путем индексации в Composite, во многом подобной значению массивов ячеек:
s{1} % Display the value of s on lab 1. All labs store the same value.
ans = 78
Кроме того, gop
, gplus
, и gcat
позволяет нам задать одну лабораторию, в которую должны быть возвращены выходы функции, и они возвращают пустой вектор в других лабораториях.
spmd s = gplus(x, 1); end s{1}
ans = 78
В этом примере показано, как выполнить множество операций, аналогичных сложению во всех лабораториях. В MPI они известны как коллективные операции, такие как MPI_SUM, MPI_PROD, MPI_MIN, MPI_MAX и т.д.
Данные, которые мы используем для всех наших примеров, очень просты: массив вариантов 1 на 2, который лишь немного сложнее x
мы определили в начале:
spmd x = labindex + (1:2) end
Lab 1: x = 2 3 Lab 2: x = 3 4 Lab 3: x = 4 5 Lab 4: x = 5 6 Lab 5: x = 6 7 Lab 6: x = 7 8 Lab 7: x = 8 9 Lab 8: x = 9 10 Lab 9: x = 10 11 Lab 10: x = 11 12 Lab 11: x = 12 13 Lab 12: x = 13 14
Теперь, когда мы инициализировали наш вектор x
для различных значений в лабораториях, мы можем задать вопросы, например, какова поэлементная сумма значений x
через лаборатории? Как насчет продукта, минимума и максимума? Как следует ожидать от нашего введения,
spmd s = gplus(x); end s{1}
ans = 90 102
возвращает сложение значений x
. Однако gplus
является только частным случаем gop
операция, сокращение от Global OPerement. The gop
функция позволяет нам выполнить любую ассоциативную операцию через лаборатории на элементах массива варианта массива. Самый основной пример ассоциативной операции - сложение; он ассоциативен, поскольку сложение не зависит от используемой группировки:
(a + b) + c = a + (b + c)
В MATLAB ® сложение может быть обозначено @plus
указатель на функцию, поэтому мы также можем записать gplus(x)
как
spmd s = gop(@plus, x); end s{1}
ans = 90 102
Мы можем конкатенировать вектор x
через лаборатории при помощи gcat
функция, и мы можем выбрать размерность, чтобы объединить вместе.
spmd y1 = gcat(x, 1); % Concatenate along rows. y2 = gcat(x, 2); % Concatenate along columns. end y1{1} y2{1}
ans = 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 ans = Columns 1 through 13 2 3 3 4 4 5 5 6 6 7 7 8 8 Columns 14 through 24 9 9 10 10 11 11 12 12 13 13 14
Просто вычислить поэлементный продукт значений x
через лаборатории:
spmd p = gop(@times, x); end p{1}
ans = 1.0e+10 * 0.6227 4.3589
Мы также можем найти элемент за элементом максимум x
через лаборатории:
spmd M = gop(@max, x); m = gop(@min, x); end M{1} m{1}
ans = 13 14 ans = 2 3
У MATLAB еще больше встроенных ассоциативных операций. Логические операции AND, OR и XOR представлены @and
, @or
, и @xor
указатели на функцию. Например, посмотрите на логический массив
spmd y = (x > 4) end
Lab 1: y = 0 0 Lab 2: y = 0 0 Lab 3: y = 0 1 Lab 4: y = 1 1 Lab 5: y = 1 1 Lab 6: y = 1 1 Lab 7: y = 1 1 Lab 8: y = 1 1 Lab 9: y = 1 1 Lab 10: y = 1 1 Lab 11: y = 1 1 Lab 12: y = 1 1
Затем мы можем легко выполнить эти логические операции над элементами y
через лаборатории:
spmd yand = gop(@and, y); yor = gop(@or, y); yxor = gop(@xor, y); end yand{1} yor{1} yxor{1}
ans = 0 0 ans = 1 1 ans = 1 0
Чтобы завершить наш тур по ассоциативным операциям, которые встроены в MATLAB, мы рассмотрим побитовые операции AND, OR и XOR. Они представлены @bitand
, @bitor
, и @bitxor
указатели на функцию.
spmd xbitand = gop(@bitand, x); xbitor = gop(@bitor, x); xbitxor = gop(@bitxor, x); end xbitand{1} xbitor{1} xbitxor{1}
ans = 0 0 ans = 15 15 ans = 0 12
Нам нужно сделать всего лишь небольшой бит программирования, чтобы найти лабиндекс, соответствующий тому, где элемент за элементом максимум x
через лаборатории происходит. Мы можем сделать это всего в нескольких строках кода:
type pctdemo_aux_gop_maxloc
function [val, loc] = pctdemo_aux_gop_maxloc(inval) %PCTDEMO_AUX_GOP_MAXLOC Find maximum value of a variant and its labindex. % [val, loc] = pctdemo_aux_gop_maxloc(inval) returns to val the maximum value % of inval across all the labs. The labindex where this maximum value % resides is returned to loc. % Copyright 2007 The MathWorks, Inc. out = gop(@iMaxLoc, {inval, labindex*ones(size(inval))}); val = out{1}; loc = out{2}; end function out = iMaxLoc(in1, in2) % Calculate the max values and their locations. Return them as a cell array. in1Largest = (in1{1} >= in2{1}); maxVal = in1{1}; maxVal(~in1Largest) = in2{1}(~in1Largest); maxLoc = in1{2}; maxLoc(~in1Largest) = in2{2}(~in1Largest); out = {maxVal, maxLoc}; end
и когда функция реализована, она может применяться так же легко, как и любая из встроенных операций:
spmd [maxval, maxloc] = pctdemo_aux_gop_maxloc(x); end [maxval{1}, maxloc{1}]
ans = 13 14 12 12
Точно так же нам нужно только несколько строк кода, чтобы найти лабиндекс, где минимальное значение элемента за элементом x
через лаборатории происходит:
type pctdemo_aux_gop_minloc
function [val, loc] = pctdemo_aux_gop_minloc(inval) %PCTDEMO_AUX_GOP_MINLOC Find minimum value of a variant and its labindex. % [val, loc] = pctdemo_aux_gop_minloc(inval) returns to val the minimum value % of inval across all the labs. The labindex where this minimum value % resides is returned to loc. % Copyright 2007 The MathWorks, Inc. out = gop(@iMinLoc, {inval, labindex*ones(size(inval))}); val = out{1}; loc = out{2}; end function out = iMinLoc(in1, in2) % Calculate the min values and their locations. Return them as a cell array. in1Smallest = (in1{1} < in2{1}); minVal = in1{1}; minVal(~in1Smallest) = in2{1}(~in1Smallest); minLoc = in1{2}; minLoc(~in1Smallest) = in2{2}(~in1Smallest); out = {minVal, minLoc}; end
Мы можем затем легко найти минимум с gop
:
spmd [minval, minloc] = pctdemo_aux_gop_minloc(x); end [minval{1}, minloc{1}]
ans = 2 3 1 1