Работа с массивами Codistributed

Как программное обеспечение MATLAB распределяет массивы

Когда вы распределяете массив многим рабочим, MATLAB® программное обеспечение делит массив в сегменты и присваивает один сегмент массива каждому рабочему. Можно разделить двумерный массив горизонтально, присвоив столбцы исходного массива различным рабочим, или вертикально, путем присвоения строк. Массив с размерностями N может быть разделен по любому из его измерений N. Вы выбираете, какая размерность массива должна быть разделена путем определения его в команде конструктора Array.

Например, чтобы распределить 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

    Worker 1: This worker stores D(:,1:250).
    Worker 2: This worker stores D(:,251:500).
    Worker 3: This worker stores D(:,501:750).
    Worker 4: This worker stores D(:,751:1000).

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

Как MATLAB отображает массив Codistributed

Для каждого рабочего Командное окно Параллели MATLAB отображает информацию о codistributed массиве, локальном фрагменте и codistributor. Например, 8 8 единичная матрица codistributed среди четырех рабочих, с двумя столбцами на каждом рабочем, отображается как это:

>> spmd
II = eye(8,"codistributed")
end
Worker 1: 
  This worker stores II(:,1:2).
          LocalPart: [8x2 double]
      Codistributor: [1x1 codistributor1d]
Worker 2: 
  This worker stores II(:,3:4).
          LocalPart: [8x2 double]
      Codistributor: [1x1 codistributor1d]
Worker 3: 
  This worker stores II(:,5:6).
          LocalPart: [8x2 double]
      Codistributor: [1x1 codistributor1d]
Worker 4: 
  This worker stores II(:,7:8).
          LocalPart: [8x2 double]
      Codistributor: [1x1 codistributor1d]

Чтобы видеть фактические данные в локальном сегменте массива, используйте getLocalPart функция.

Сколько распределяется каждому рабочему

В распределении массива N строки, если N является равномерно делимым количеством рабочих, MATLAB хранит одинаковое число строк (N/numlabs) на каждом рабочем. Когда этот номер не является равномерно делимым количеством рабочих, MATLAB делит массив максимально равномерно.

MATLAB обеспечивает codistributor свойства объектов под названием Dimension и Partition то, что можно использовать, чтобы определить точное распределение массива. Смотрите Индексацию в Массив Codistributed для получения дополнительной информации об индексации с codistributed массивами.

Распределение других типов данных

Можно распределить массивы любого MATLAB встроенный тип данных, и также числовые массивы, которые являются комплексными или разреженными, но не массивы указателей на функцию или типов объектов.

Создание массива Codistributed

Можно создать codistributed массив любым из следующих способов:

  • Разделение Большего Массива — Запускается с большого массива, который реплицирован во всех рабочих, и разделите его так, чтобы части были распределены на рабочих. Это является самым полезным, когда у вас есть достаточная память, чтобы сохранить реплицированный массив начальной буквы.

  • Создание от Меньших массивов — Запускается с меньших различных или реплицированных массивов, сохраненных на каждом рабочем, и комбинирует их так, чтобы каждый массив стал сегментом большего codistributed массива. Этот метод уменьшает требования к памяти, когда он позволяет вам создать codistributed массив из мелких кусочков.

  • Используя Функции конструктора MATLAB — Использование любая из функций конструктора MATLAB как rand или zeros с codistributor возражают аргументу. Эти функции предлагают быстрые средние значения построения codistributed массива любого размера всего на одном шаге.

Разделение большего массива

Если у вас уже есть большой массив в памяти, что вы хотите 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

Исследуя переменные в клиентской рабочей области, массив, который является codistributed среди рабочих в spmd оператор, распределенный массив с точки зрения клиента вне spmd оператор. Переменными, которые не являются codistributed в spmd, являются Составные объекты в клиенте вне spmd.

whos  
  Name        Size               Bytes  Class                   Attributes

  A           1x4                  489  Composite                         
  D           4x8                  256  distributed                       

Смотрите codistributed страница ссылки на функцию для синтаксиса и информации об использовании.

Создание от меньших массивов

codistributed функция менее полезна для сокращения объема памяти, требуемого хранить данные, когда вы сначала создаете полный массив в одной рабочей области и затем делите его в распределенные сегменты. Чтобы экономить на памяти, можно создать мелкие кусочки (локальная часть) на каждом рабочем сначала, и затем использовать codistributed.build объединить их в единый массив, который распределяется на рабочих.

Этот пример создает 4 250 различный массив на каждом из четырех рабочих и затем использует codistributor распределить эти сегменты на четырех рабочих, создавая 4 1000 codistributed массив. Вот различный массив, 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
Worker 1: 
    This worker stores D(1:4,:).
           LocalPart: [4x250 double]
      Codistributor: [1x1 codistributor1d]

whos   
Name       Size             Bytes  Class          Attributes

A          1x4                489  Composite                
D         16x250            32000  distributed 

Вы могли также использовать реплицированные массивы тем же способом, если бы вы хотели создать codistributed массив, сегменты которого были все идентичны, чтобы запуститься с. Смотрите codistributed страница ссылки на функцию для синтаксиса и информации об использовании.

Используя функции конструктора MATLAB

MATLAB обеспечивает несколько функций конструктора Array, которые можно использовать, чтобы создать codistributed массивы определенных значений, размеров и классов. Эти функции действуют таким же образом в качестве своих нераспределенных дубликатов на языке MATLAB, за исключением того, что они распределяют результирующий массив на рабочих, использующих заданный объект codistributor, codist.

Функции конструктора.  codistributed функции конструктора перечислены здесь. Используйте 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)

Локальные массивы

Та часть codistributed массива, который находится на каждом рабочем, является частью большего массива. Каждый рабочий может работать над его собственным сегментом обычного массива, или он может сделать копию того сегмента в различном или частном собственном массиве. Эта локальная копия codistributed сегмента массивов называется локальным массивом.

Создание локальных массивов от массива Codistributed

getLocalPart функционируйте копирует сегменты codistributed массива к отдельному различному массиву. Этот пример делает локальную копию L из каждого сегмента codistributed массива 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

Каждый рабочий распознает что codistributed массив D 3 80. Однако заметьте что размер локальной части, L, находится 3 20 на каждом рабочем, потому что 80 столбцов D распределяются по четырем рабочим.

Создание Codistributed от локальных массивов

Используйте codistributed.build функция, чтобы выполнить противоположную операцию. Эта функция, описанная в Создании от Меньших массивов, комбинирует локальные различные массивы в единый массив, распределенный в заданном измерении.

При продолжении предыдущего примера возьмите локальные различные массивы L и соединенный их как сегменты, чтобы создать новый codistributed массив X.

spmd
  codist = codistributor1d(2,[20 20 20 20],[3 80]);
  X = codistributed.build(L,codist);
  size(X)
end

возвращается на каждом рабочем:

3    80

Получение информации О Массиве

MATLAB предлагает несколько функций, которые предоставляют информацию о каком-то конкретном массиве. В дополнение к этим стандартным функциям существует также две функции, которые полезны только с codistributed массивами.

Определение, является ли массив Codistributed

iscodistributed функция возвращает логический 1 TRUE) если входной массив является codistributed и логическим 0 ложь) в противном случае. Синтаксис

spmd, TF = iscodistributed(D), end

где D любой массив MATLAB.

Определение размерности распределения

Объект codistributor определяет, как массив разделен и его размерность распределения. Чтобы получить доступ к 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

Другие функции массива

Другие функции, которые предоставляют информацию о стандартных массивах также, работают над codistributed массивами и используют тот же синтаксис.

  • length — Возвращает длину определенной размерности.

  • ndims — Возвращает количество размерностей.

  • numel — Возвращает число элементов в массиве.

  • size — Возвращает размер каждой размерности.

  • is* — Много функций, которые имеют имена, начинающиеся с 'is', такой как ischar и issparse.

Изменение размерности распределения

При построении массива вы распределяете части массива по одному из измерений массива. Можно изменить направление этого распределения на существующем массиве с помощью redistribute функция с различным объектом codistributor.

Создайте 8 16 codistributed массив 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

Восстановление полного массива

Можно восстановить codistributed массив к его нераспределенной форме с помощью 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
Worker 1: 
    4     3
Worker 2: 
    4     3
Worker 3: 
    4     2
Worker 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

Индексация в массив Codistributed

В то время как индексация в нераспределенный массив является довольно прямой, codistributed массивы требуют дополнительных факторов. Каждая размерность нераспределенного массива индексируется в диапазоне 1 к итоговому индексу, который представлен в MATLAB end ключевое слово. Длина любой размерности может быть легко определена с помощью любого size или length функция.

С codistributed массивами так легко не получены эти значения. Например, второй сегмент массива (то, что находится в рабочей области рабочего 2) имеет начальное значение индекса, которое зависит от распределения массивов. Для 200 1000 массива с распределением по умолчанию столбцами более чем четыре рабочих, начальное значение индекса на рабочем 2 251. Для 1000 200 массива, также распределенного столбцами, тот же самый индекс был бы 51. Что касается конечного индекса, это не дано при помощи end ключевое слово, как end в этом случае относится в конец целого массива; то есть, последний индекс итогового сегмента. Длина каждого сегмента также не дана при помощи length или size функции, когда они только возвращают длину целого массива.

colon MATLAB оператор и end ключевое слово является двумя из основных инструментов для индексации в нераспределенные массивы. Для codistributed массивов MATLAB обеспечивает версию colon оператор, названный codistributed.colon. Это на самом деле - функция, не символьный оператор как colon.

Примечание

При использовании массивов, чтобы индексировать в codistributed массивы, можно использовать только реплицированные или codistributed массивы для индексации. Тулбокс не проверяет, чтобы гарантировать, что индекс реплицирован, когда это потребовало бы глобальной связи. Поэтому использование неподдерживаемых вариантов (такой как labindex) индексировать в codistributed массивы может создать неожиданные результаты.

Пример: найдите конкретный элемент в массиве Codistributed

Предположим, что у вас есть вектор-строка из 1 миллиона элементов, распределенных среди нескольких рабочих, и вы хотите определить местоположение его элемента номер 225,000. Таким образом, вы хотите знать, какой рабочий содержит этот элемент, и в какой положение в локальной части вектора на том рабочем. globalIndices функция обеспечивает корреляцию между локальной и глобальной индексацией codistributed массива.

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

Если при запуске этот код по пулу четырех рабочих, вы получаете этот результат:

Worker 1: 
  Element is in position 225000 on worker 1.

Если при запуске этот код по пулу пяти рабочих, вы получаете этот результат:

Worker 2: 
  Element is in position 25000 on worker 2.

Заметьте, используете ли вы пул различного размера, элемент заканчивается в другом месте на различном рабочем, но тот же код может использоваться, чтобы определить местоположение элемента.

2-мерное Распределение

Как альтернатива распределению одной размерностью строк или столбцов, можно распределить матрицу блоками с помощью '2dbc' или двумерное циклическое блоком распределение. Вместо сегментов, которые включают много полных строк или столбцов матрицы, сегменты codistributed массива являются 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 рабочих, и размер блока является квадратом четырех элементов на стороне (i.e., каждый блок является квадратом 4 на 4). С этой информацией можно задать объект codistributor:

spmd
    DIST = codistributor2dbc([2 2], 4);
end

Теперь можно использовать этот объект codistributor распределить исходную матрицу:

spmd
    AA = codistributed(A, DIST)
end

Это распределяет массив среди рабочих согласно этой схеме:

Если сетка лаборатории отлично не накладывает размерности codistributed массива, можно все еще использовать '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
Worker 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
  
Worker 2: 
  
  ans =
  
      25    33    41
      26    34    42
      27    35    43
      31    39    47
      32    40    48
  
Worker 3: 
  
  ans =
  
       4    12    20    52    60
       5    13    21    53    61
       6    14    22    54    62
  
Worker 4: 
  
  ans =
  
      28    36    44
      29    37    45
      30    38    46

Следующие моменты стоит отметить:

  • '2dbc' распределение не может предложить улучшение эффективности, если размер блока не по крайней мере несколько дюжин. Размер блока по умолчанию равняется 64.

  • Сетка лаборатории должна быть максимально близко к квадрату.

  • Не все функции, которые улучшены, чтобы работать над '1d' массивы codistributed работают над '2dbc' массивы codistributed.