Работа с массивами 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

    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 отображает массив Codistributed

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

>> 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, который можно использовать, чтобы определить точное распределение массива. Смотрите Индексацию в Массив 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 

  A         1x4               613  Composite
  D         4x8               649  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
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 массив, сегменты которого были все идентичны, чтобы запуститься с. Смотрите страницу ссылки на функцию 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 (false) в противном случае. Синтаксис

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 массивами и используют тот же синтаксис.

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

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

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

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

  • 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
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

Индексация в массив 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

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

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

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

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

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

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

Как альтернатива распределению одной размерностью строк или столбцов, можно распределить матрицу блоками с помощью '2dbc' или двумерного циклического блоком распределения. Вместо сегментов, которые включают много полных строк или столбцов матрицы, сегменты codistributed массива являются 2-мерными квадратными блоками.

Например, считайте простое 8 8 матрицей с возрастающими значениями элемента. Можно создать этот массив в операторе spmd, передав задание или pmode. Этот пример использует pmode для отображения.

P>> A = reshape(1:64, 8, 8)

Результатом является реплицированный массив:

     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:

P>> DIST = codistributor2dbc([2 2], 4)

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

P>> AA = codistributed(A, DIST)

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

Если сетка лаборатории отлично не накладывает размерности codistributed массива, можно все еще использовать распределение '2dbc', которое является циклическим блоком. В этом случае можно вообразить сетку лаборатории, неоднократно накладываемую в обеих размерностях, пока все исходные элементы матрицы не включены.

Используя тот же оригинал 8 8 матричная и сетка лаборатории 2 на 2, рассмотрите размер блока 3 вместо 4, так, чтобы 3х3 квадратные блоки были распределены среди рабочих. Код выглядит так:

P>> DIST = codistributor2dbc([2 2], 3)
P>> AA = codistributed(A, DIST)

Первая “строка” сетки лаборатории распределяется рабочему 1 и рабочему 2, но это содержит только шесть из восьми столбцов исходной матрицы. Поэтому следующие два столбца распределяются рабочему 1. Этот процесс продолжается, пока все столбцы в первых строках не распределяются. Затем подобный процесс применяется к строкам, в то время как вы продолжаете вниз матрица, как показано в следующей схеме распределения:

Схема выше показов схема, которая требует, чтобы четыре оверлейных программ сетки лаборатории разместили целую исходную матрицу. Следующий pmode сеанс показывает код и получившееся распределение данных каждому из рабочих:

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

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

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

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