При распределении массива по нескольким работникам программа MATLAB ® разбивает массив на сегменты и назначает один сегмент массива каждому работнику. Двумерный массив можно разделить по горизонтали, назначив столбцы исходного массива различным работникам, или по вертикали, назначив строки. Массив с N размерами может быть разделен вдоль любого из его N размеров. Для выбора размера массива, подлежащего секционированию, необходимо указать его в команде конструктора массива.
Например, чтобы распределить массив 80 на 1000 для четырех работников, можно разделить его либо по столбцам, давая каждому работнику сегмент 80 на 250, либо по строкам, при этом каждый работник получает сегмент 20 на 1000. Если измерение массива не делится равномерно по количеству работников, MATLAB разбияет его как можно более равномерно.
В следующем примере создается реплицированный массив 80 на 1000, который назначается переменной A. При этом каждый работник создает идентичный массив в своей рабочей области и назначает его переменной A, где A является локальным по отношению к этому работнику. Вторая команда распределяет A, создание единого массива 80 на 1000 D это охватывает всех четырех рабочих. Рабочий 1 хранит столбцы с 1 по 250, рабочий 2 хранит столбцы с 251 по 500 и т.д. Распределение по умолчанию - по последнему несинглтонному измерению, таким образом, столбцы в данном случае 2-мерного массива.
spmd
A = zeros(80, 1000);
D = codistributed(A)
end
Lab 1: This lab stores D(:,1:250).
Lab 2: This lab stores D(:,251:500).
Lab 3: This lab stores D(:,501:750).
Lab 4: This lab stores D(:,751:1000).
Каждый работник имеет доступ ко всем сегментам массива. Доступ к локальному сегменту выполняется быстрее, чем к удаленному сегменту, поскольку последний требует отправки и приема данных между работниками и, таким образом, занимает больше времени.
Для каждого работника в окне параллельных команд MATLAB отображается информация о распределенном по коду массиве, локальной части и распространителе кодов. Например, матрица идентичности 8 на 8, распределенная между четырьмя работниками, с двумя столбцами на каждом работнике, отображается следующим образом:
>> spmd
II = eye(8,'codistributed')
end
Lab 1:
This lab stores II(:,1:2).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]
Lab 2:
This lab stores II(:,3:4).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]
Lab 3:
This lab stores II(:,5:6).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]
Lab 4:
This lab stores II(:,7:8).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]Для просмотра фактических данных в локальном сегменте массива используйте getLocalPart функция.
При распределении массива N строки, если N равномерно делится на количество работников, MATLAB хранит одинаковое количество строк (N/numlabs) на каждого работника. Если это число не делится равномерно на число работников, MATLAB разбияет массив как можно более равномерно.
MATLAB предоставляет свойства объекта codistributor с именем Dimension и Partition , который можно использовать для определения точного распределения массива. Дополнительные сведения об индексировании с использованием распределенных по коду массивов см. в разделе Индексирование в распределенный по коду массив.
Можно распределять массивы любого встроенного типа данных MATLAB, а также числовые массивы, которые являются сложными или разреженными, но не массивы дескрипторов функций или типов объектов.
Можно создать распределенный массив одним из следующих способов:
Разбиение большего массива - начните с большого массива, который реплицируется на всех работников, и разбиение его таким образом, чтобы части распределялись между работниками. Это наиболее удобно при наличии достаточного объема памяти для хранения исходного реплицированного массива.
Создание из меньших массивов - начните с меньших вариантов или реплицированных массивов, хранящихся на каждом работнике, и объедините их таким образом, чтобы каждый массив стал сегментом большего распределенного по кодам массива. Этот метод снижает требования к памяти, так как позволяет создавать распределенный по коду массив из небольших частей.
Использование функций конструктора MATLAB - использование любой из функций конструктора MATLAB, например rand или zeros с аргументом объекта codistributor. Эти функции предлагают быстрое средство построения совместно распределенного массива любого размера всего за один шаг.
Если у вас уже есть большой массив в памяти, который вы хотите, чтобы MATLAB обрабатывался быстрее, вы можете разделить его на меньшие сегменты и распределить эти сегменты всем работникам с помощью codistributed функция. Затем каждый работник имеет массив, который является долей размера оригинала, что сокращает время, необходимое для доступа к данным, которые являются локальными для каждого работника.
В качестве простого примера, следующая строка кода создает реплицированную матрицу 4 на 8 для каждого работника, назначенного переменной A:
spmd, A = [11:18; 21:28; 31:38; 41:48], end
A =
11 12 13 14 15 16 17 18
21 22 23 24 25 26 27 28
31 32 33 34 35 36 37 38
41 42 43 44 45 46 47 48В следующей строке используется codistributed функция для построения одной матрицы 4 на 8 D которая распределена по второму измерению массива:
spmd
D = codistributed(A);
getLocalPart(D)
end
1: Local Part | 2: Local Part | 3: Local Part | 4: Local Part
11 12 | 13 14 | 15 16 | 17 18
21 22 | 23 24 | 25 26 | 27 28
31 32 | 33 34 | 35 36 | 37 38
41 42 | 43 44 | 45 46 | 47 48Множества A и D одинаковый размер (4 на 8). Множество A существует в полном размере на каждом работнике, в то время как только сегмент массива D существует на каждом работнике.
spmd, size(A), size(D), end
Анализ переменных в клиентской рабочей области - массиве, который распределяется между работниками внутри spmd оператор - распределенный массив с точки зрения клиента вне spmd заявление. Переменные, которые не распределены внутри spmd, являются Composites в клиенте вне spmd.
whos Name Size Bytes Class A 1x4 613 Composite D 4x8 649 distributed
См. раздел codistributed справочная страница функции для синтаксиса и информации об использовании.
codistributed функция менее полезна для уменьшения объема памяти, необходимой для хранения данных, когда сначала создается полный массив в одной рабочей области, а затем он разделяется на распределенные сегменты. Чтобы сэкономить на памяти, можно сначала построить меньшие части (локальную деталь) на каждом работнике, а затем использовать codistributed.build чтобы объединить их в единый массив, распределенный по работникам.
В этом примере создается массив вариантов 4 на 250 A для каждого из четырех работников, а затем используется codistributor чтобы распределить эти сегменты между четырьмя работниками, создайте массив с кодовым распределением 4 на 1000. Вот массив вариантов, A:
spmd
A = [1:250; 251:500; 501:750; 751:1000] + 250 * (labindex - 1);
end
WORKER 1 WORKER 2 WORKER 3
1 2 ... 250 | 251 252 ... 500 | 501 502 ... 750 | etc.
251 252 ... 500 | 501 502 ... 750 | 751 752 ...1000 | etc.
501 502 ... 750 | 751 752 ...1000 | 1001 1002 ...1250 | etc.
751 752 ...1000 | 1001 1002 ...1250 | 1251 1252 ...1500 | etc.
| | |Теперь объедините эти сегменты в массив, который распределяется по первому размеру (строкам). Массив теперь 16 на 250, а сегмент 4 на 250 расположен на каждом работнике:
spmd
D = codistributed.build(A, codistributor1d(1,[4 4 4 4],[16 250]))
end
Lab 1:
This lab stores D(1:4,:).
LocalPart: [4x250 double]
Codistributor: [1x1 codistributor1d]
whos
Name Size Bytes Class
A 1x4 613 Composite
D 16x250 649 distributedРеплицированные массивы можно также использовать таким же образом, если требуется создать распределенный по коду массив, сегменты которого идентичны для начала. См. раздел codistributed справочная страница функции для синтаксиса и информации об использовании.
MATLAB предоставляет несколько функций конструктора массива, которые можно использовать для построения совместно распределенных массивов с определенными значениями, размерами и классами. Эти функции работают так же, как их нераспределенные аналоги на языке MATLAB, за исключением того, что они распределяют результирующий массив по работникам с помощью указанного объекта codistributor, codist.
Функции конструктора. Здесь перечислены функции распределенного конструктора. Используйте codist аргумент (созданный codistributor функция: codist=codistributor()) для указания размера для распределения массива. Для получения дополнительной информации о синтаксисе и использовании см. отдельные справочные страницы этих функций.
eye(___,codist)false(___,codist)Inf(___,codist)NaN(___,codist)ones(___,codist)rand(___,codist)randi(___,codist)randn(___,codist)true(___,codist)zeros(___,codist)codistributed.cell(m,n,...,codist)codistributed.colon(a,d,b) codistributed.linspace(m,n,...,codist) codistributed.logspace(m,n,...,codist)sparse(m,n,codist)codistributed.speye(m,...,codist)codistributed.sprand(m,n,density,codist)codistributed.sprandn(m,n,density,codist)
Та часть совместно распределенного массива, которая находится на каждом работнике, является частью большего массива. Каждый работник может работать со своим собственным сегментом общего массива или сделать копию этого сегмента в собственном варианте или частном массиве. Эта локальная копия сегмента coddistributed массива называется локальным массивом.
getLocalPart функция копирует сегменты совместно распределенного массива в отдельный массив вариантов. В этом примере создается локальная копия L каждого сегмента распределенного по кодам массива D. Размер L показывает, что он содержит только локальную часть D для каждого работника. Предположим, что массив распределяется между четырьмя работниками:
spmd(4)
A = [1:80; 81:160; 161:240];
D = codistributed(A);
size(D)
L = getLocalPart(D);
size(L)
end
возврат для каждого работника:
3 80 3 20
Каждый работник распознает, что распределенный по коду массив D 3 на 80. Однако обратите внимание, что размер локальной детали, L, составляет 3 на 20 на каждом работнике, потому что 80 столбцов D распределяются по четырем рабочим.
Используйте codistributed.build для выполнения обратной операции. Эта функция, описанная в разделе Построение из меньших массивов, объединяет локальные массивы вариантов в один массив, распределенный вдоль указанного размера.
Продолжая предыдущий пример, возьмите локальные массивы вариантов L и собрать их вместе в виде сегментов для построения нового распределенного по кодам массива X.
spmd codist = codistributor1d(2,[20 20 20 20],[3 80]); X = codistributed.build(L,codist); size(X) end
возврат для каждого работника:
3 80
MATLAB предлагает несколько функций, которые предоставляют информацию о каком-либо конкретном массиве. В дополнение к этим стандартным функциям, существуют также две функции, которые полезны исключительно с распределенными по коду массивами.
iscodistributed функция возвращает логическое 1 (true), если входной массив является кодовым и логическим 0 (false) в противном случае. Синтаксис:
spmd, TF = iscodistributed(D), end
где D - любой массив MATLAB.
Объект coddistributor определяет способ секционирования массива и его размерность распределения. Для доступа к codistributor массива используйте getCodistributor функция. Это возвращает два свойства, Dimension и Partition:
spmd, getCodistributor(X), end
Dimension: 2
Partition: [20 20 20 20]
Dimension значение 2 означает массив, X распределяется по столбцам (размерность 2); и Partition значение [20 20 20 20] означает, что двадцать колонн находятся на каждом из четырех рабочих.
Чтобы получить эти свойства программным путем, верните выходные данные getCodistributor к переменной, затем использовать точечную нотацию для доступа к каждому свойству:
spmd
C = getCodistributor(X);
part = C.Partition
dim = C.Dimension
endДругие функции, предоставляющие информацию о стандартных массивах, также работают на кодовых распределенных массивах и используют тот же синтаксис.
При построении массива детали массива распределяются по одному из размеров массива. Можно изменить направление этого распределения в существующем массиве с помощью redistribute с другим объектом codistributor.
Создание распределенного по кодам массива 8 на 16 D случайных значений, распределенных по столбцам на четырех работниках:
spmd
D = rand(8,16,codistributor());
size(getLocalPart(D))
endвозврат для каждого работника:
8 4
Создайте новый распределенный по строкам массив из существующего, уже распределенного по столбцам:
spmd
X = redistribute(D, codistributor1d(1));
size(getLocalPart(X))
endвозврат для каждого работника:
2 16
Можно восстановить нераспределенный массив в его нераспределенную форму с помощью gather функция. gather принимает сегменты массива, которые находятся на разных рабочих участках, и объединяет их в реплицированный массив на всех рабочих участках или в один массив на одном рабочем участке.
Распределите массив 4 на 10 для четырех работников по второму измерению:
spmd, A = [11:20; 21:30; 31:40; 41:50], end
A =
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
spmd, D = codistributed(A), end
WORKER 1 WORKER 2 WORKER 3 WORKER 4
11 12 13 | 14 15 16 | 17 18 | 19 20
21 22 23 | 24 25 26 | 27 28 | 29 30
31 32 33 | 34 35 36 | 37 38 | 39 40
41 42 43 | 44 45 46 | 47 48 | 49 50
| | |
spmd, size(getLocalPart(D)), end
Lab 1:
4 3
Lab 2:
4 3
Lab 3:
4 2
Lab 4:
4 2Восстановите нераспределенные сегменты в полной форме массива, собрав сегменты:
spmd, X = gather(D), end
X =
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
spmd, size(X), end
4 10В то время как индексация в нераспределенный массив довольно проста, для кодовых распределенных массивов требуются дополнительные соображения. Каждое измерение нераспределенного массива индексируется в диапазоне от 1 до конечного подстрочного индекса, который представлен в MATLAB end ключевое слово. Длина любого размера может быть легко определена с помощью size или length функция.
При использовании совместно распределенных массивов эти значения не так легко получить. Например, второй сегмент массива (который находится в рабочей области worker 2) имеет начальный индекс, который зависит от распределения массива. Для массива 200 на 1000 с распределением по умолчанию по столбцам для четырех работников начальный индекс для работника 2 равен 251. Для массива 1000 на 200, также распределенного по столбцам, этот же индекс будет равен 51. Что касается конечного индекса, это не дается с помощью end ключевое слово, как end в этом случае относится к концу всего массива; то есть последний нижний индекс конечного сегмента. Длина каждого сегмента также не задается с помощью length или size функции, поскольку они возвращают только длину всего массива.
MATLAB colon оператор и end ключевое слово - это два основных инструмента для индексирования в нераспределенные массивы. Для распределенных по коду массивов MATLAB предоставляет версию colon оператор, вызываемый codistributed.colon. На самом деле это функция, а не символический оператор, как colon.
Примечание
При использовании массивов для индексации в распределенные массивы можно использовать только реплицированные или распределенные массивы для индексирования. Панель инструментов не проверяет репликацию индекса, поскольку для этого потребуется глобальная связь. Поэтому использование неподдерживаемых вариантов (например, labindex) индексация в распределенные массивы может привести к непредвиденным результатам.
Предположим, что у вас есть вектор строки из 1 миллиона элементов, распределенный между несколькими работниками, и вы хотите найти его элемент номер 225 000. То есть, вы хотите знать, какой работник содержит этот элемент и в какой позиции в локальной части вектора на этом работнике. globalIndices функция обеспечивает корреляцию между локальным и глобальным индексированием распределенного по коду массива.
D = rand(1,1e6,'distributed'); %Distributed by columns
spmd
globalInd = globalIndices(D,2);
pos = find(globalInd == 225e3);
if ~isempty(pos)
fprintf(...
'Element is in position %d on worker %d.\n', pos, labindex);
end
endПри запуске этого кода в пуле из четырех работников получается следующий результат:
Lab 1: Element is in position 225000 on worker 1.
При запуске этого кода на пуле из пяти работников получается следующий результат:
Lab 2: Element is in position 25000 on worker 2.
Обратите внимание, что при использовании пула другого размера элемент оказывается в другом месте на другом работнике, но для определения местоположения элемента можно использовать тот же код.
В качестве альтернативы распределению по одному размеру строк или столбцов можно распределить матрицу по блокам с помощью '2dbc' или двумерное блочно-циклическое распределение. Вместо сегментов, которые содержат несколько полных строк или столбцов матрицы, сегменты совместно распределенного массива являются 2-мерными квадратными блоками.
Например, рассмотрим простую матрицу 8 на 8 со значениями восходящего элемента. Этот массив можно создать в spmd заявление или передающее задание.
spmd
A = reshape(1:64, 8, 8)
endРезультатом является реплицированный массив:
1 9 17 25 33 41 49 57
2 10 18 26 34 42 50 58
3 11 19 27 35 43 51 59
4 12 20 28 36 44 52 60
5 13 21 29 37 45 53 61
6 14 22 30 38 46 54 62
7 15 23 31 39 47 55 63
8 16 24 32 40 48 56 64Предположим, что необходимо распределить этот массив между четырьмя работниками, с блоком 4 на 4 в качестве локальной детали на каждом работнике. В этом случае сетка лаборатории представляет собой расположение рабочих 2 на 2, а размер блока представляет собой квадрат из четырех элементов на стороне (т.е. каждый блок представляет собой квадрат 4 на 4). С помощью этой информации можно определить объект codistributor:
spmd
DIST = codistributor2dbc([2 2], 4);
endТеперь можно использовать этот объект codistributor для распределения исходной матрицы:
spmd
AA = codistributed(A, DIST)
endПри этом массив распределяется между работниками в соответствии со следующей схемой:

Если сетка лаборатории не полностью перекрывает размеры распределенного массива, можно использовать '2dbc' распределение, которое является блочным циклическим. В этом случае можно представить, что сетка лаборатории многократно накладывается в обоих измерениях до тех пор, пока не будут включены все исходные элементы матрицы.
Используя ту же исходную матрицу 8 на 8 и лабораторную сетку 2 на 2, рассмотрим размер блока 3 вместо 4, так что квадратные блоки 3 на 3 распределяются между рабочими. Код выглядит следующим образом:
spmd
DIST = codistributor2dbc([2 2], 3)
AA = codistributed(A, DIST)
endПервая «строка» лабораторной сетки распределяется между работником 1 и работником 2, но содержит только шесть из восьми столбцов исходной матрицы. Поэтому следующие два столбца распределяются по рабочему 1. Этот процесс продолжается до тех пор, пока не будут распределены все столбцы в первых строках. Затем аналогичный процесс применяется к строкам при переходе вниз по матрице, как показано на следующей схеме распределения:

На схеме выше показана схема, требующая четырех наложений сетки лаборатории для размещения всей исходной матрицы. Следующий код показывает результирующее распределение данных по каждому из работников.
spmd
getLocalPart(AA)
endLab 1:
ans =
1 9 17 49 57
2 10 18 50 58
3 11 19 51 59
7 15 23 55 63
8 16 24 56 64
Lab 2:
ans =
25 33 41
26 34 42
27 35 43
31 39 47
32 40 48
Lab 3:
ans =
4 12 20 52 60
5 13 21 53 61
6 14 22 54 62
Lab 4:
ans =
28 36 44
29 37 45
30 38 46Следует отметить следующие моменты:
'2dbc' дистрибутив может не предложить повышения производительности, если размер блока не превышает нескольких десятков. Размер блока по умолчанию равен 64.
Сетка лаборатории должна быть как можно ближе к квадрату.
Не все функции, которые расширены для работы с '1d' codtisted массивы работают на '2dbc' распределенные массивы.