Примери за разпределени масиви

Въведение

Разпределението на данните между процесите има за цел да ускори изчислението и да спести памет. Паралелното изчисление с използване на разпределени масиви е описано подробно на уебсайта на Matlab, по-специално в подраздела Работа с съвместно разпределени масиви.

Възможен е достъп до всеки сегмент от разпределения масив. Достъпът до локален сегмент ще бъде по-бърз от достъпа до отдалечен сегмент, тъй като последният изисква изпращане (функция labSend) и получаване (функция labReceive) на данни между процесите. Съдържанието на разпределен масив може да бъде събрано с помощта на функцията за събиране в един локален масив, като се дублира във всички процеси или се постави само в един процес.

Използването на разпределени масиви в паралелни изчисления намалява времето за изчисление поради факта, че всеки процес обработва своя собствена локална част от оригиналния масив (сегмент от разпределения масив).

Има 3 начина за създаване на разпределен масив (вижте Създаване на съвместно разпределен масив): 1) разделяне на оригиналния масив на части, 2) изграждане от локални части (по-малки масиви), 3) използване на вградени функции на Matlab (като rand, нули, . ).

1) Разделянето на масив на части може да бъде реализирано с помощта на функцията codistributed (Пример 1). В същото време първоначалният масив в неговата цялост и съответният сегмент от разпределения масив се намират в работното пространство на всеки процес. Следователно този метод е добър, ако има достатъчно място в паметта за съхраняване на репликирания изходен масив. Размерите на изходния и разпределения масив са еднакви.

Масивът може да бъде разделен по всяко от неговите измерения. По подразбиране в случай на двуизмерен масив се извършва хоризонтално разделяне, т.е. отколони, което изглежда естествено, като се вземе предвид подреждането на матриците в паметта по колони (както във Fortran), прието в системата Matlab.

2) Когато се изгражда разпределен масив от локални части, масивът, съхраняван в работното пространство на всеки процес, се приема като сегмент от разпределения масив (Пример 2). По този начин разпределеният масив се разглежда като обединение на локални масиви. В този случай изискванията за памет са намалени.

3) За вградени функции на Matlab (като rand, нули, . ), можете да създадете разпределен масив с произволен размер в една стъпка (вижте Използване на функции на конструктор на MATLAB).

Най-гореКак могат да се използват разпределени масиви

В примерите по-долу решението на проблема включва изчисляване на стойностите на някаква функция, означена my_func. В същото времеизчисляването на една функционална стойност изисква много време.

Дадени са възможни схеми за решаване на такива задачи с помощта на разпределени масиви. Показан е преходът от оригиналната последователна програма към паралелна с разпределени изчисления. Съответните промени са подчертани.Забележка. Въпреки че разпределителните масиви са съвместими (за разлика от цикъла parfor и GPU) с глобални променливи, трябва да се внимава, за да се гарантира, че промените в глобалните променливи по време на обработката на една част от данните не засягат резултатите от обработката на други части, като по този начин се гарантира независимост на изчисленията на части от разпределителните масиви. Където е уместно, по-лесно е да използвате цикъл на parfor или изчисления наGPU.

Най-гореПример 1. Разделяне на масив на части

Нека се изисква да се изчислят стойностите на някаква функция от 10 реални променливи. Аргументът на функцията е 10-измерен вектор. Необходима е стойност на функциятаизчисляване за n точки (стойности на аргумент), дадени от 10xn матрица. Матрицата се изчислява по някакъв зададен алгоритъм и не изисква много време.

Нотация. my_func - изчислена функция M - масив за аргументи на функция my_func F - масив за стойности на функция my_func ​​ M_distr - разпределен масив за M (същото измерение) F_distr - разпределен масив за F (същото измерение)

функция test_1() % инициализация на данни n=1000; . % резервиране на памет M = нули (10,n); F = нули (1,n); % запълване на матрицата M .функция test_1() % инициализация на данни n = 1000; . % резервиране на памет M = нули (10,n); F = нули (1,n); % запълване на матрицата M . % създаване на разпределени масиви % разделянето по подразбиране се извършва от % колони (2-ро измерение)M_distr = codistributed(M); F_distr = codistributed(F);% оценка на функция за i = 1:n F(1,i) = my_func(M(:,i)); край% изчисление на функциятаза i = drange(1:size(M_distr,2)) F_distr(1,i) = my_func(M_distr(:,i)); end % колекция от резултати за 1-ви процесF = gather(F_distr,1);save('test_res_1.mat', 'F', 'M');ако labindex == 1 запазване ('test_res_1.mat', 'F', 'M');крайвръщане крайвръщане край

ГореПример 2. Изграждане на масив от части. Разпределен масив като обединение на локални масиви

Генерирайте таблица с функционални стойности на 2 реални променливи ((x,y) --> F) върху правоъгълна мрежа 120x200, дефинирана от вектори (x1:x2:x3 и y1:y2:y3). Има алгоритъм за изчисляване на стойността на функция в точка, означена като my_func.

Нотация. my_func - изчислена функция от 2 променливи F - масив за стойностите на функцията my_func ​​ F_loc - локален масив, който се запълва със съответните стойности на функцията за всеки процес и след това се взема като основа (считана за сегмент) при изграждане на разпределен масив F_distr F_distr - разпределен масив, чието съдържание се събира в масив F на 1-ви процес

Вариант 1. Успоредяването се извършва по външния цикъл (по x - първият индекс). Предполага се, че броят на редовете 120 е кратен на numlabs - броя на процесите, подредени при стартиране на програмата в акаунта.

функция test_2() % инициализация на данни, % по-специално % x1, x2, x3, y1, y2, y3 .функция test_2() % инициализация на данни, % по-специално % x1, x2, x3, y1, y2, y3 .m_x = x1:x2:x3; n = 120/numlabs;% разпределение на паметта F = нули (120,200); % изчисление на функция i = 1; за x = x1:x2:x3 .% разпределение на паметтаF_loc = нули (n,200); % оценка на функцията% i = 1;за i = 1:n k = (labindex-1)*n + i; x = m_x(k);.j = 1; за y = y1:y2:y3 F(i,j) = my_func(x,y); j = j + 1; край i = i + 1; крайj = 1; за y = y1:y2:y3F_loc(i,j) = my_func(x,y); j = j + 1; край% i = i + 1; край % паралелизиране, извършено на редове % (1-во измерение) => codistributor1d(1, . )codist = codistributor1d(1, [], [120 200]); F_distr = codistributed.build(F_loc, codist); F = събиране (F_distr, 1);save('test_res_2.mat', 'F');ако labindex == 1 запазване ('test_res_2.mat', 'F');крайвръщане крайвръщане край

Вариант 2. Успоредяването се извършва по вътрешния цикъл (по y - вторият индекс). Предполага се, че броят на колоните 200 е кратно на numlabs - броя процеси, подредени в началото на програмата за акаунт.

функция test_2() % инициализация на данни, % по-специално % x1, x2, x3, y1, y2, y3 .функция test_2() % инициализация на данни, % по-специално % x1, x2, x3, y1, y2, y3 .m_y = y1:y2:y3; n = 200/numlabs;% разпределение на паметта F = нули (120,200); % изчисление на функция i = 1; за x = x1:x2:x3 . j = 1; за y = y1:y2:y3% разпределение на паметтаF_loc = нули (120,n); % оценка на функцията i = 1; за x = x1:x2:x3 .% j = 1;за j = 1:n k = (лабиндекс-1)*n + j; y = m_y(k);F(i,j) = my_func(x,y); j = j + 1; край i = i + 1; крайF_loc(i,j) = my_func(x,y);% j = j + 1; край i = i + 1; край % паралелизиране в колони % (2-ро измерение) => codistributor1d(2, . )codist = codistributor1d(2, [], [120 200]); F_distr = codistributed.build(F_loc, codist); F = събиране (F_distr, 1);save('test_res_2.mat', 'F');ако labindex == 1 запазване ('test_res_2.mat', 'F');крайвръщане крайвръщане край

Забележка. Тази задача, ако има достатъчно памет, може да се програмира по първия начин, т.е. чрез разделяне на голям масив на части. В този случай разпределението на данните между процесите ще се извършва автоматично (изискването за множественост изчезва).

НагореКак да се уверите, че програмата работи

Преди първото стартиране на функционална програма на клъстер, тя трябва първо да бъде проверенаеднопроцесорен вариант с дебъгерDebug (вижте например Debug a MATLAB Program) и след това в паралелен режимpmode. Тъй катополитиката за използване на изчислителни ресурси на IMM Ural Branch на Руската академия на науките не включва дългосрочни изчисления на контролния компютър, трябва да стартирате програмата в режимиDebug иpmode с набор от тестови данни.

Затова се препоръчва следната последователност на извеждане към акаунта:Debugpmode cluster

Можете да стартирате режимаpmode на 4 процеса (за по-голяма яснота) в прозореца на Matlab (Команден прозорец), като използвате командата pmode start 4 След това в командния ред на отворения паралелен прозорец (Параллелен команден прозорец), извикайте вашата програма. Можете да затворите паралелния режим или от паралелния прозорец с командата exit или от прозореца на Matlab с командата pmode exit Функцията getLocalPart е полезна за контрол на данни.

Изпълнението на клъстер може да се извърши в прозореца на Matlab с помощта на функцията imm_sch.