Характеристики на рамкиране

Има няколко функции, които се използват във всяко, дори и най-краткото MPI приложение. Те се занимават не толкова с реалното предаване на данни, колкото с предоставянето им:

Инициализиране на библиотеката. Една от първите инструкции в основната функция (основната функция на приложението):

Срив на библиотеката. Извиква се, ако потребителската програма се прекрати поради свързани с MPI грешки по време на изпълнение:

MPI_Abort(дескриптор на областта на връзката, MPI код на грешка);

Извикването на MPI_Abort от която и да е задача принудително ще прекрати ВСИЧКИ задачи, свързани към посочената област на връзка. Ако е указан дескрипторът MPI_COMM_WORLD, цялото приложение (всички негови задачи) ще бъде прекратено, което очевидно е най-правилното решение. Използвайте кода за грешка MPI_ERR_OTHER, ако не сте сигурни как да характеризирате грешка в MPI класификацията.

Нормално затваряне на библиотеката:

Трябва да въведете тази инструкция, преди да се върнете от програмата, а именно:

ü преди извикване на стандартната C функция за изход;

ü преди всеки оператор return след MPI_Init в основната функция;

ü ако на функцията main е присвоен тип void и тя не завършва с израз за връщане, тогава MPI_Finalize() трябва да се постави в края на main.

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

Пример за използването на тези функции е във файла “pi_mpi.c” - намиране на числото Pi. Той използва, в допълнение към вече познатите функции, MPI_Bcast и MPI_Reduce. Тези функции се обсъждат в параграфите: MPI_Bcast - Мултикаст функции; MPI_Reduce - Функции за поддръжкаразпределени операции).

2.4. Комуникация от точка до точка

Това е най-простият тип комуникация между задачите: единият клон извиква функцията за предаване на данни, а другият извиква функцията за получаване. В MPI изглежда така:

Задача 1 изпраща:

MPI_Send(buf, 5, MPI_INT, 1, 0, MPI_COMM_WORLD);

Задача 2 отнема:

MPI_Recv(buf, 10, MPI_INT, 0, 0, MPI_COMM_WORLD, &състояние);

1. Адресът на буфера, от който се вземат данни в задача 1 и данните се поставят в задача 2. Не забравяйте, че всяка задача има свои собствени набори от данни, следователно, например, използвайки едно и също име на масив в няколко задачи, вие посочвате не една и съща област на паметта, а различни, които не са свързани помежду си по никакъв начин.

2. Размер на буфера. Посочва се не в байтове, а в броя на клетките. За MPI_Send указва колко клетки да бъдат изпратени (в примера се изпращат 5 числа). В MPI_Recv означава максималния капацитет на приемния буфер. Ако действителната дължина на входящото съобщение е по-малка - последните клетки на буфера ще останат непокътнати, ако е по-голяма - ще възникне грешка по време на изпълнение.

3. Тип буферна клетка. MPI_Send и MPI_Recv работят с масиви от същия тип данни. За да опише основните C типове, MPI дефинира константите MPI_INT, MPI_CHAR, MPI_DOUBLE и т.н., които имат тип MPI_Datatype. Имената им се образуват от префикса "MPI_" и името на съответния тип (int, char, double, . ), изписани с главни букви. Потребителят може да "регистрира" свои собствени типове данни, като структури, с MPI, след което MPI може да ги обработва наравно с основните.

4.Номер на задачата, с която се обменят данни. Всички задачи в група, създадена от MPI, автоматично се номерират от 0 до (размер на групата-1). В примера задача 0 изпраща към задача 1, задача 1 получава от задача 0.

5. Идентификатор на съобщението. Това е цяло число от 0 до 32767, което потребителят избира. Той служи за същата цел като например файловото разширение - целева задача:

ü чрез идентификатор определя значението на получената информация;

ü Съобщенията, пристигнали в неизвестен ред, могат да бъдат извлечени от общия входен поток в реда, изискван от алгоритъма. Добра практика е да обозначавате идентификатори със символни имена, като използвате операторите "#define" или "const int".

6. Описание на комуникационната област (комуникатор). Трябва да е същото за MPI_Send и MPI_Recv.

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

2.5. Получаване и предаване: MPI_Sendrecv

Някои проекти за предаване и приемане се използват много често. Пример - обмен на данни със съседи в група (за четен брой клонове в група):

/* Първо четните клонове

* преминете към следващите нечетни клонове,

* след това приемете от предишните

MPI_Send(. (ранг+1) % размер.);

MPI_Recv(. (ранг+размер-1) % размер.);

/* Странните клонове правят обратното:

* първо вземане от предишни клонове,

* след това се преминава към следващия.

MPI_Recv(. (ранг-1) % размер.);

MPI_Send(. (ранг+1) % размер.);

Друг пример е изпращане на данни и получаване на потвърждение:

MPI_Send(. anyRank .); /* Изпращане на данни */

MPI_Recv(. anyRank . ); /* Приемане на потвърждение */

Ситуацията е толкова разпространена, че MPI специално въведе две функции, които едновременно изпращат едни данни и получават други. Първият е MPI_Sendrecv. Има 12 параметъра:първите 5 параметъра са същите като за MPI_Send, останалите 7 параметъра са същите като за MPI_Recv. Едно извикване към него прави същите неща, които изискват блок IF-ELSE с четири извиквания в първия фрагмент. Трябва да бъде отбелязано че:

ü както приемането, така и предаването използват един и същ комуникатор;

ü MPI_Sendrecv автоматично избира реда на получаване и предаване на данни; гарантирано е, че автоматичният избор няма да доведе до "клинч";

ü MPI_Sendrecv е съвместим с MPI_Send и MPI_Recv, т.е. може да "комуникира" с тях.

MPI_Sendrecv_replace, в допълнение към общия комуникатор, използва и общ буфер за приемане и предаване. Не е много удобно параметърът за броене да получава двойна интерпретация: това е едновременно количеството изпратени данни и максималният капацитет на входния буфер. Показания за употреба:

ü получените данни трябва да са явно НЕ ПО-ДЪЛГИ от изпратените;

ü получените и изпратените данни трябва да са от един и същи тип;

Изпратените данни се презаписват от получените данни.

MPI_Sendrecv_replace също е гарантирано, че няма да предизвика клинч.

Клинч (deadlock, deadlock) - процесът е в състояние на безизходица, ако чака събитие, което никога няма да се случи. пример за клинч:

-- Клон 1 -- -- Клон 2 --

Recv(от клон 2) Recv(от клон 1)

Изпрати( до клон 2 ) Изпрати( до клон 1 )

Това ще доведе до затруднение: функцията за получаване няма да се върне, докато не получи данни; следователно функцията за изпращане не може да започне да изпраща данни; така че функцията за получаване. и така до самия SIG_KILL.

Колективни функции

Терминът "колективен" в MPI се отнася до три групи функции:

ü функции за колективен обмен на данни;

ü точки на синхронизация или бариери;

ü поддържащи функцииразпределени операции.

Колективната функция получава дескриптор на комуникационната област (комуникатор) като един от аргументите. Извикването на колективна функция е правилно само ако е направено от всички абонатни процеси на съответната област на свързване и с този комуникатор като аргумент (въпреки че може да има няколко комуникатора за една област на свързване, те не могат да бъдат заменени един с друг). Това е същността на колективността: или дадена функция се извиква от целия екип от процеси, или от никой; Трети няма.

За да се ограничи обхватът на колективната функция до част от клоновете, на базата на съществуващите се създава временна група/област за връзка/комуникатор, както е показано в раздела за комуникатори.