Когда вы распределяете массив ряду работников, 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 Parallel Командное Окно отображается информация о кодовом массиве, локальном фрагменте и кодовом распространителе. Для примера матрица тождеств 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, а также числовые массивы, которые являются сложными или разреженными, но не массивами указателей на функцию или типов объектов.
Вы можете создать codistributed array любым из следующих способов:
Секционирование Большого Массива - начните с большого массива, который реплицируется на всех рабочих местах, и разделите его так, чтобы части были распределены между рабочими. Это наиболее полезно, когда у вас достаточно памяти для хранения исходного реплицированного массива.
Построение из меньших массивов - начните с меньшего варианта или реплицированных массивов, хранящихся на каждом рабочем месте, и объедините их, чтобы каждый массив стал сегментом большего кодового распределенного массива. Этот метод уменьшает требования к памяти, так как позволяет вам создавать кодовый распределенный массив из небольших частей.
Использование функций MATLAB Constructor - Используйте любую из функций конструктора MATLAB, таких как rand
или zeros
с аргументом объект. Эти функции предлагают быстрое средство построения кодируемого массива любого размера всего за один шаг.
Если у вас уже есть большой массив в памяти, который вы хотите, чтобы 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
чтобы объединить их в один массив, который распределен между работниками.
Этот пример создает вариант массива A 4 на 250 для каждого из четырех рабочих процессов, а затем использует 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)
Та часть кодового распределенного массива, которая находится на каждом рабочем месте, является частью большего массива. Каждый рабочий процесс может работать со своим собственным сегментом обычного массива, или он может сделать копию этого сегмента в собственном варианте или частном массиве. Эта локальная копия сегмента кодового распространения массива называется локальным массивом.
The 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.
Объект codistributor определяет, как разделяется массив и его размерность распределения. Для доступа к codistributor массива используйте getCodistributor
функция. Это возвращает два свойства, Dimension
и Partition
:
spmd, getCodistributor(X), end Dimension: 2 Partition: [20 20 20 20]
The 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
Создайте новый codistributed массив, распределенный по строкам из существующего, уже распределенного по столбцам:
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
функция.
С кодированными массивами эти значения не так легко получить. Например, второй сегмент массива (тот, что находится в рабочей области работника 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) end
Lab 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'
codistributed array работает с '2dbc'
codistributed arrays.