Вы находитесь на странице: 1из 19

1.

Системы DMM(Distributed Memory Model) и SMM(Shared Memory Model)


1.1. ​SMM ​- все процессоры используют общую память, для обмена информацией

DMM​- каждый использует свою память, для обмена информацией

1.2.
Системы с распределенной памятью
В системах этого типа на каждом вычислительном узле функционирует собственные копии
операционной системы, под управлением которых выполняются независимые программы.
Это могут быть как действительно независимые программы, так и параллельные ветви одной
программы. В этом случае единственно возможным механизмом взаимодействия между ними
является механизм передачи сообщений. Этот механизм реализуется в виде прикладных
библиотек, которые должны подключаться к параллельной программе.
Для систем с распределенной памятью широко применяется интерфейс MPI—Message
Passing Interface.
Message Passing
● Метод передачи данных из памяти одного процессора в память другого
● Данные пересылаются в виде пакетов
● Сообщение может состоять из одного или нескольких пакетов
Стандарт MPI-1 включает в себя следующие базовые функции:

1) управление вычислительным окружением,


2) передача сообщений типа “точка-точка”,
3) коллективные операции взаимодействия,
4) использование производных типов данных,
5) управление группами и коммуникаторами,
6) виртуальные топологии.
Отличительной особенностью программ, написанных с использованием стандарта MPI-1,
состоит в том, что в них допускается только статическое
распараллеливание, т.е., количество параллельных процессов во время запуска и исполнения
программы фиксировано.
Стандарт MPI-2, помимо функциональности стандарта MPI-1, включает в себя
функции:

1) динамического порождения процессов,


2) однонаправленной передачи сообщений,
3) расширенных коллективных операций,
4) параллельного ввода/вывода.

Системы с общей памятью


В системах с общей памятью, как правило, единственная копия операционной системы
управляет работой всех процессоров и всей памятью. Основная модель программирования -
"fork-join" (Ветвление - Объединение). Любая программа стартует как обычная
однопроцессорная программа. При достижении параллельной части программы, головная
программа (мастер) порождает некоторое число дополнительных процессов (ветвей), которые
завершаются по окончании параллельной части.
Для организации такой модели вычислений могут использоваться стандартные средства
операционной системы, такие как процесс, нить (thread) или высокоуровневые средства
параллельного программирования, например, OpenMP.

2. //todo
2.1 Критические секции
Критическая секция -​это область кода, в котором вследствие некоторых
последовательностей разного доступа, могут генерироваться различные результаты.
Сущности доступа это потоки или процессы. Ссылаясь на критическую зону, также
можно подразумевать набор данных, которые могут быть открыты для доступа для
большего количества процессов/потоков.
Критическая секция, к которой доступ не синхронизирован (т.е не может быть
гарантирована четкая последовательность доступа) генерирует так называемые
условия гонки (race condition). Появление подобного условия может генерировать
разные результаты в одинаковых контекстах.
Пример критической секции представлен в виде псевдокода:
Ex1 Ex2
a := 0 for i = 1 to 15 do
for i = 1 to 15 do a := a + 1
a := a + 1 end
end
print (a)

Для синхронизации данной критической области необходимо разрешить доступ


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

пациента из кабинета, для того , чтобы получить консультацию.

2.2 Взаимное исключение ​.


Критические логические секции подразумевают поочередную работу процессов с
ними. Процесс, который вступил в свою критически-логическую секцию отстраняет от
выполнения любой другой текущий процесс, отсюда следует что происходит
взаимное исключение ​процессов между собой.
Правила взаимного исключения:
1. В каждый момент , как минимум один процесс находится в своей критической
секции
2. Если ни один процесс не находится в своей критической секции и если
существуют процессы которые хотят войти в свои критические секции, тогда
одни из них эффективно войдет в свою критическую секцию
3. Если один процесс “опаздывает” в свою некритическую область, эта ситуация
не должна мешать другим процессам вступать в свою критическую область
3. Compilation and execution
Compile​- /opt/openmpi/bin/mpiCC -o example. example.cpp
Run​- /opt/openmpi/bin/mpirun -n 8 -host compute-0-0,compute-0-2 att.exe
-n 8​число процессов
-host compute-0-0,compute-0-2 ​процессоры
4. Найти число пи (3.4.4)
4.1. Интервал [0,1] разделяется на n частей(подинтервал) и находится площади
прямоугольников всех частей. Каждому процессу соответствует свой подинтервал. Т. Е.
каждый процесс находит площадь своего прямоугольника и потом они складываются.

4.2 Параллелизация на уровне данных


MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD
отправка каждому процессу значение n, которое мы ввели для ранка 0
/*
MPI_Bcast(mass, count, type, N0, Comm)
mass Адрес начала буфера для приема сообщения
count Число элементов принимаемого массива
type Тип элемента принимающего массива
N0 Номер процесса-отправителя
*/
4.3 Параллелизация на уровне операции
MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
/*
MPI_Reduce(mass_s, mass_r, count_r, type_r, op, N0, Comm)
mass_s Адрес, с которого начинается пересылаемый участок информации
mass_r Адрес начала буфера для приема сообщения
count_r Количество элементов принимаемого сообщения
type_r Тип элемента данных принимаемого сообщения
op Название операции
N0 Номер принимающего процесса
*/
5. MPI and OpenMP (3.4.4)
5.1.
MPI - ​modele de programare paralelă cu memorie distribuită (распределенная память)
OpenMP - ​modele de programare paralelă cu memorie partajată (общая память)
5.2. Основных х-ки
OpenMP ​- это способ программирования на устройствах с общей памятью. Это
означает, что параллелизм имеет место, когда каждый параллельный поток имеет
доступ ко всем вашим данным.
Вы можете думать об этом как: параллелизм может произойти во время выполнения
определенного цикла путем разделения цикла между различными потоками.
OpenMP - использует набор стандартных функций и директив компилятора, которые
выполняют локальные потоки параллельно, и вы контролируете поведение этих
потоков (к какому ресурсу они должны иметь доступ, как они синхронизируются и т.
Д.).
MPI​- это способ программирования на устройствах с распределенной
памятью. Это означает, что параллелизм возникает там, где каждый параллельный
процесс работает в своем собственном пространстве памяти изолированно от других.
Вы можете думать об этом как: каждый бит кода, который вы написали, выполняется
независимо каждым процессом. Параллелизм возникает потому, что вы точно
указываете каждому процессу, над какой частью задачи работать, основываясь
исключительно на их идентификаторе процесса.
6. ~/nodes Exemplu4.2.2.exe
int main (int argc, char *argv[])
{
int my_rank;
omp_set_num_threads(_NUM_THREADS);
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
int c=0, Sum_c;
#pragma omp parallel reduction(+:c)
{
c = 1;
}
MPI_Reduce(&c, &Sum_c, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (my_rank == 0)
printf("Total number =%d \n", Sum_c);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
return 0;
}

/*
[Hancu_B_S@hpc Open_MP]$ /opt/openmpi/bin/mpirun -n 8 -machinefile
The count of threads on the MPI process 7 of the compute node '--compute0-1.local--' is 2
...
The count of threads on the MPI process 3 of the compute node '--compute0-0.local--' is 2
Total number of threads=16
6.1. Определение общего числа процессов(потоков) всех хостов.
Для 1 процессора ( -n 1) результат Total number = 2 --- (1 процессор * 2 потока)
Для 2 процессора ( -n 2) результат Total number = 4 --- (2 процессор * 2 потока)

Для 4 процессора ( -n 4) результат Total number = 8 --- (4 процессор * 2 потока)


Для 5 процессора ( -n 5) результат Total number = 10--- (5 процессор * 2 потока)

6.2. ​#pragma omp parallel reduction(+:c) ( так объявляется критическая секция)


The​omp parallel​указывает компилятору что надо параллелизовать следующий блок {}
reduction (operator: list)
Performs a reduction on all scalar variables in list using the specified operator. Reduction variables
in list are separated by commas.
A private copy of each variable in list is created for each thread. At the end of the statement block,
the final values of all private copies of the reduction variable are combined in a manner appropriate
to the operator, and the result is placed back in the original value of the shared reduction variable.
В нашем случае для каждого потока внутри {} с = 1. у нас 2 потока значит к с = 0 из
программы прибавим два раза 1. в результате в ​MPI_Reduce приходит с = 2;

7. MPI and OpenMP (3.4.4)


Compilation /opt/openmpi/bin/mpiCC -fopenmp -o pr7.exe pr7.cpp
Running /opt/openmpi/bin/mpirun -n 1 -host compute-0-0,compute-0-2 pr7.exe
#include <omp.h>
#include <stdio.h>
main(){
int​i, n, chunk;
float​a[​100​], b[​100​], result;
n ​=​​100​;
chunk ​=​​ 10​;
result ​=​​0.0​;

for​(i ​=​​0​; i ​<​n; i​++​){


a[i] ​=​i ​*​​1.0​;
b[i] ​=​i ​*​​2.0​;
}
#pragma omp_for parallel default(shared) private(i) schedule(static,chunk) reduction (+:result)
for​(i ​=​​0​; i ​<​n; i​++​){
result ​ =​result ​+​(a[i] ​*​b[i]);
}
printf(​"Final result= %f​\n​"​, result);
}
7.1. Пример использования директивы reduction. В данном примере вычисляется
скалярное произведение двух векторов. Final result= 656700.000000
7.2. ​#pragma omp parallel​- Constructorul de regiuni paralele. Scopul acestuia: o regiune
paralela este un bloc de cod care va fi executat de mai multe fire. Este constructul paralel OpenMP
fundamental.
Директива​parallel​указывает, что структурный блок кода должен быть выполнен параллельно
в несколько ​потоков​.
Использование специальной ключевой директивы «omp» указывает на то, что команды
относятся к OpenMP. Таким образом директивы #pragma для работы с OpenMP имеют
следующий формат:
#pragma omp <директива> [раздел [ [,] раздел]...]
Директива ​#pragma omp for ​сообщает, что при выполнении цикла for в параллельном регионе
итерации цикла должны быть распределены между потоками группы:
Теперь каждый создаваемый поток будет обрабатывать только отданную ему часть массива.
Относительно параллельных регионов данные могут быть общими (​shared)​или частными
(​private​). Частные данные принадлежат потоку и могут быть модифицированы только им.
Общие данные доступны всем потокам.
shedule(static)

Chunks​are groups of iterations (in contiguous order) that are assigned to threads (размер куска
кода/блока)

Программист может контролировать то, каким образом потоки будут загружаться работой
при обработке цикла. Существует несколько вариантов.
static ​является вариантом по умолчанию. Ещё до входа в цикл каждый поток «знает», какие
части цикла он будет обрабатывать.
Static​-​Divide the loop into equal-sized chunks or as equal as possible in the case where the number
of loop iterations is not evenly divisible by the number of threads multiplied by the chunk size. By
default, chunk size is loop_count/number_of_threads.Set chunk to 1 to interleave the iterations.
(https://software.intel.com/en-us/articles/openmp-loop-scheduling)
Второй вариант - ключевое слово ​dynamic​:
В данном случае невозможно предсказать порядок, в котором итерации цикла будут
назначены потокам. Каждый поток выполняет указанное число итераций. Если это число не
задано, по умолчанию оно равно 1. После того как поток завершит выполнение заданных
итераций, он переходит к следующему набору итераций.
Dynamic - ​Use the internal work queue to give a chunk-sized block of loop iterations to each thread.
When a thread is finished, it retrieves the next block of loop iterations from the top of the work
queue. By default, the chunk size is 1.
Dynamic​schedule - each thread grabs "chunk" iterations until all iterations are done. Faster threads
are assigned more iterations

Директива reduction
Формат директивы: reduction(оператор: список)
Возможные операторы — "+", "*", "-", "&", "|", "^", "&&", "||".
Принцип работы:

1. Для каждой переменной создаются локальные копии в каждом потоке.


2. Локальные копии инициализируются соответственно типу оператора. Для аддитивных
операций — 0 или его аналоги, для мультипликативных операций — 1 или ее аналоги.
Смотри также таблицу N1.
3. Над локальными копиями переменных после выполнения всех операторов
параллельной области выполняется заданный оператор. Порядок выполнения
операторов не определен.

https://habr.com/company/intel/blog/88574/
7.3. Ce schimbari sunt necesare in program pentru a modifica distribuirea pe fire a operatiilor?
Возможно -> schedule(​dynamic​)

8. (3.5.3.) похож проверить еще раз (Гриша)


8.1.
int main(int argc, char *argv[]) {
int i, p, size, size_new, rank, rank_new, sour, dest;
int rank_gr;
MPI_Status status;
MPI_Comm com_new, ring1;
MPI_Group MPI_GROUP_WORLD, newgr;

int dims[1], period[1], reord;


int ranks[5] = {1, 3, 4, 7, 9};
int D1 = 123, D2;

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

//​Доступ к группе, связанной с данным коммуникатором


MPI_Comm_group(MPI_COMM_WORLD, &MPI_GROUP_WORLD);
​//Включает в MPI_GROUP_WORLD 5 процессов с ранками из ranks в новую группу
MPI_Group_incl(MPI_GROUP_WORLD, 5, ranks, &newgr);
​//создает новый коммуникатор для группы
MPI_Comm_create(MPI_COMM_WORLD, newgr, &com_new);
​//Returns the rank of this process in the given group
MPI_Group_rank(newgr, &rank_gr);

if (rank_gr != MPI_UNDEFINED) {
MPI_Comm_size(com_new, &size_new);
MPI_Comm_rank(com_new, &rank_new);

dims[0] = size_new; // numarul de procesoare


period[0] = 1; //1 - daca e inchisa
reord = 1;

MPI_Barrier(com_new);

​//realizara topologiei de tip cerc


// Создает новый коммуникатор на основании старого
// ndims - число осей
// dims - массив, в котором хранится число процессов для каждой оси
// periods - периодичное условие для ребер ( нет условия)
​// reorder - нужно ли производить перенумерацию процессов. 1 = da
MPI_Cart_create(com_new, 1, dims, period, reord, &ring1);
/*
int MPI_Cart_shift(MPI_Comm comm, int direction, int disp, int *rank_source, int
*rank_dest)
ring1 communicator with cartesian structure (handle)
1 coordinate dimension of shift (в какой оси смещение)
2 displacement (> 0: upwards shift, < 0: downwards shift) (integer) (на сколько
смещать)
sour rank of source process (integer)
dest rank f destination process (integer)
*/
MPI_Cart_shift(ring1, 1, 2, &sour, &dest);

D1 = D1 + rank;
MPI_Sendrecv(&D1, 1, MPI_INT, dest, 12, &D2, 1, MPI_INT, sour, 12, ring1, &status);
/*
D1 - initial address of send buffer (choice) (что будем передавать)
dest - rank of destination (integer) (кому передавать)
D2 - initial address of receive buffer (choice)(что будем получать)
sour - rank of source (integer) ((от кого получать))
*/
printf("Process %d(%d), received from %d the %f and send to %d the %f\n",
rank_new, rank, sour, D2, dest, D1 );
MPI_Group_free(&newgr);
MPI_Comm_free(&ring1);
MPI_Comm_free(&com_new);
}

MPI_Finalize();
return 0;
}

8.2.
8.3.
int ranks[5] = {1, 3, 4, 7, 9};
----для 6 не будет работать. тк в ranks используются ранки больше чем 5. Для : процессов
допустимы ранки : {0, 1, 2, 3, 4, 5}
----/home/F_gr_TI42/DOLOMANJI/test$ /opt/openmpi/bin/mpirun -n 12 -host
compute-0-0,compute-0-1,compute-0-2,compute-0-3 a.exe
Process 3(7), received from 1 and send to 0
Process 1(3), received from 4 and send to 3
Process 4(9), received from 2 and send to 1
Process 2(4), received from 0 and send to 4
Process 0(1), received from 3 and send to 2

9.
#include <mpi.h>
#include <stdio.h>
int​​main​(​int​argc, ​char​**​argv)
{
int​universe_size[count] ​=​{​4​,​2​,​3​};
char​​*​worker_program[count] ​=​{​"/A_1.exe"​, ​"/A_2.exe"​, ​"/A_3.exe"​};
MPI_Init(​&​argc, ​&​argv);

MPI_Comm_spawn_multiple(count, worker_program, args, universe_size, hostinfo, ​0​,


MPI_COMM_SELF, ​&​everyone, err);
MPI_Finalize();
}
Calling MPI_COMM_SPAWN multiple times would create many sets of children with different
MPI_COMM_WORLDs whereas MPI_COMM_SPAWN_MULTIPLE creates children with a
single MPI_COMM_WORLD, so the two methods are not completely equivalent.

MPI_COMM_SPAWN_MULTIPLE​(​count, array_of_commands, array_of_argv,


array_of_maxprocs, array_of_info, root, comm, intercomm, array_of_errcodes​)

IN count number of commands (positive integer, significant to MPI only at


root) => ​numarul de programe care urmeaza a fi executate
IN programs to be executed (array of strings, significant only at root) ​=>
array_of_command массив, который содержит названия программ для
s выполнения

IN array_of_argv arguments for commands (array of array of strings, significant only at


root) ​=> массив, который содержит аргументы, которые
передаются программам

IN maximum number of processes to start for each command (array of


array_of_maxprocs integer, significant only at root) ​=> массив, содержащий
максимальное количество процессов для выполнения
программ из​​array_of_commands

IN array_of_info info objects telling the runtime system where and how to start
processes (array of handles, significant only at root)

IN root rank of process in which previous arguments are examined (integer)


=> процесс с рангом 0

IN comm intracommunicator containing group of spawning processes (handle)

OUT intercomm intercommunicator between original group and newly spawned group
(handle) ​=> для общения предков с потомками

OUT one error code per process (array of integer)


array_of_errcodes

MPI_COMM_SPAWN_MULTIPLE​is identical to​MPI_COMM_SPAWN ​except that there are


multiple executable specifications.

int MPI_Comm_spawn​(​char *command, char **argv, int maxprocs, MPI_Info info, int root,
MPI_Comm comm, MPI_Comm *intercomm, int *array_of_errcodes​) - запускает ряд
процессов ​MPI​и устанавливает с ними связь, возвращая интеркоммуникатор.

IN command Имя порождаемой программы (строка, важна только


для root)

IN argv Аргументы команды (массив строк, важен только для


root)

IN maxprocs Максимальное число процессов для запуска (целое,


важно только для root)
IN info Набор пар ключ-значение, сообщающий системе
выполнения, где и как запускать процессы
(дескриптор, важен только для root)

IN root Ранг процесса, для которого анализируются


предыдущие аргументы (целое)

IN comm Интеркоммуникатор, содержащий группу


порожденных процессов (дескриптор)

OUT intercomm Интеркоммуникатор между первичной и вновь


порожденной группой (дескриптор)

OUT array_of_errcodes Один код на процесс (массив целых)

MPI_COMM_SPAWN пытается запустить maxprocs одинаковых копий программы MPI,


определяемой command, устанавливая с ними соединение и возвращая интеркоммуникатор.
Порожденные процессы называются потомками, а процессы, их породившие, родителями.
Потомки имеют свой собственный MPI_COMM_WORLD, отдельный от родителей.
Процедура MPI_COMM_SPAWN является коллективной для comm, и не завершается, пока в
потомках не вызовется MPI_INIT. Подобным образом, MPI_INIT в потомках не завершается,
пока все родители не вызовут MPI_COMM_SPAWN. В этом смысле, MPI_COMM_SPAWN в
родителях и MPI_INIT в потомках формируют коллективную операцию над объединением
родительских и дочерних процессов. Интеркоммуникатор, возвращаемый
MPI_COMM_SPAWN, содержит родительские процессы в локальной группе и
процессы-потомки в удаленной группе. Порядок процессов в локальной и удаленной группах
такой же, как и порядок группы comm для родителей и MPI_COMM_WORLD для потомков.
Этот интеркоммуникатор может быть получен в потомке через функцию
MPI_COMM_GET_PARENT.

9.1. ​Indicati numarul total de procese MPI generate


9 процессов
9.2. ​Pe cate procese MPI vor fi executate A_1.exe, A_2.exe, A_3.exe?
A_1.exe - 4
A_2.exe - 2
A_3.exe - 3
9.3.​​Descrieti utilitarul mpirun pentru executarea programului MPI_Spawn.exe
/opt/openmpi/bin/mpirun -n 2 -host compute-0-0,compute-0-2 Exemplu_3_7_2.exe ,​т.к. мы
указываем 2 хоста.(Георгиенко говорит, на 1 процесс. Но я проверяла - не работает)
10.
#include <mpi.h>
#include <stdio.h>
int​​main​(​int​argc, ​char​**​argv)
{
int​rank, count, x, amode, i, j;
MPI_File OUT;
MPI_Aint rowsize;
MPI_Datatype etype,ftype0,ftype1,ftype2;
int​value[​4​][​8​];
MPI_Status state;
MPI_Datatype MPI_ROW;
int​blengths[​2​]​=​{​0​,​1​};
MPI_Datatype types[​2​];
MPI_Aint disps[​2​];
MPI_Init(​&​argc,​&​argv);
MPI_Comm_rank(MPI_COMM_WORLD,​&​rank);
amode ​=​MPI_MODE_CREATE​|​MPI_MODE_WRONLY;

MPI_File_open(MPI_COMM_WORLD,​"array.dat"​,amode,MPI_INFO_NULL,​&​OUT);
MPI_Type_contiguous(​8​,MPI_INT,​&​MPI_ROW);
MPI_Type_commit(​&​MPI_ROW);

etype ​=​MPI_ROW;
ftype0 ​=​MPI_ROW;

types[​0​] ​=​types[​1​] ​=​MPI_ROW;


disps[​0​] ​=​(MPI_Aint) ​0​;

MPI_Type_extent(MPI_ROW,​&​rowsize);
disps[​1​] ​=​​2​*​rowsize;

MPI_Type_struct(​2​,blengths,disps,types,​&​ftype1);
MPI_Type_commit(​&​ftype1);
disps[​1​] ​=​​3​*​rowsize;

MPI_Type_struct(​2​,blengths,disps,types,​&​ftype2);
MPI_Type_commit(​&​ftype2);

if​(rank ​==​​0​) {
MPI_File_set_view(OUT,​0​,etype,ftype0,​"native"​,MPI_INFO_NULL);
}
if​(rank ​==​​1​){
MPI_File_set_view(OUT,​0​,etype,ftype1,​"native"​,MPI_INFO_NULL);
}

if​(rank ​==​​2​){
MPI_File_set_view(OUT,​0​,etype, ftype2,​"native"​,MPI_INFO_NULL);
}

for​(i​=​1​;i​<=​4​;​++​i){
for​(j​=​1​;j​<=​8​;​++​j){
value[i​-​1​][j​-​1​]​=​​10​*​i​+​j;
}
}
count​=​0​;

// Inscrierea in paralel a datelor in fisierul "array.dat"


if​(rank ​==​​0​){

MPI_File_write(OUT,​&​value[rank][​0​],​1​,MPI_ROW,​&​state);
MPI_Get_count(​&​state,MPI_ROW,​&​x);
count​=​count ​+​x;

MPI_File_write(OUT,​&​value[rank​+​1​][​0​],​1​,MPI_ROW,​&​state);
MPI_Get_count(​&​state,MPI_ROW,​&​x);
count​=​count ​+​x;

printf(​"P:%d %d etypes written​\n​"​,rank,count);

} ​else​{
MPI_File_write(OUT,​&​value[rank​+​1​][​0​],​1​,MPI_ROW,​&​state);
MPI_Get_count(​&​state,MPI_ROW,​&​count);

printf(​"P:%d %d etypes written​\n​"​,rank,count);


}

MPI_File_close(​&​OUT);
MPI_Finalize();
}

10.1 ​Descrieti functiile MPI din acest program utilizate pentru lucrul cu fisiere
MPI_File_write()​- записать фиксированный блок данных в файл начиная с текущей позиции.
int MPI_File_write( MPI_File​fh, ​ROMIO_CONST void​*buf, ​int​count, ​MPI_Datatype
datatype, ​MPI_Status​*status​)
fh ​- ​имя файла для записи
buf ​- ​начальный адрес буфера памяти
count ​- ​количество элементов в буфере
datatype ​- ​тип данных каждого элемента буфера

int MPI_File_open(
​MPI_Comm​​comm,​
​char​*​filename​,
​int​​amode,​
​MPI_Info​​info​,
​MPI_File​*​mpi_fh
);
MPI_FILE_OPEN opens the file identified by the file name filename on all processes in the
comm communicator group.
comm - ​
коммуникатор
filename ​- имя файла
amode ​- режим доступа к файлу
info ​- информация об объекте
mpi_fh ​- дескриптор файла. ​A ​file handle​is an opaque object created by MPI_FILE_OPEN and
freed by MPI_FILE_CLOSE. All operations on an open file reference the file through the file
handle.

int MPI_File_set_view(
​MPI_File​​mpi_fh​,
​MPI_Offset​​disp,​
​MPI_Datatype​​etype​,
​MPI_Datatype​​filetype,​
​char​*​datarep​,
​MPI_Info​​info
);
Подпрограмма ​MPI_FILE_SET_VIEW​изменяет вид данных файла для процесса.
mpi_fh - ​дескриптор файла
disp - ​смещение
etype - ​элементарный тип данных (дескриптор)
filetype -​тип файла (дескриптор)
datarep - ​представление данных (строка)
info -​информационный объект (дескриптор)
MPI_File_close​- ​MPI_File_close first synchronizes file state, then closes the file associated with
fh.​MPI_File_close is a collective routine. The user is responsible for ensuring that all outstanding
requests associated with ​fh​have completed before calling MPI_File_close.

Бонус
int MPI_Get_count​(​MPI_Status​status, ​MPI_Datatype ​datatype, ​int ​*count )

Через параметр ​count ​возвращает длину сообщения. Обычно вызывается после MPI_Probe.
• status информация о сообщении
• datatype тип принимаемых элементов
• выходной параметр count - число элементов сообщения
Производные типы MPI не являются в полном смысле типами данных, как это понимается в
языках программирования. Они не могут использоваться ни в каких других операциях, кроме
коммуникационных. Производные типы MPI следует понимать как описатели расположения
в памяти элементов базовых типов. Производный тип MPI представляет собой скрытый
(opaque) объект, который специфицирует две вещи: последовательность базовых типов и
последовательность смещений. Последовательность таких пар определяется как
отображение (карта) типа​.
int MPI_Type_contiguous​(int count, MPI_Datatype oldtype, MPI_Datatype *newtype)
Самый простой ​конструктор типа MPI_Type_contiguous​создает новый тип, элементы
которого состоят из указанного числа элементов базового типа, занимающих смежные
области памяти.
Конструктор типа MPI_Type_struct​- самый универсальный из всех конструкторов типа.
Создаваемый им тип является структурой, состоящей из произвольного числа блоков,
каждый из которых может содержать произвольное число элементов одного из базовых типов
и может быть смещен на произвольное число байтов от начала размещения структуры.
int MPI_Type_struct​(int count, int *array_of_blocklengths, MPI_Aint *array_of_displacements,
MPI_Datatype *array_of_types, MPI_Datatype *newtype)
Функция MPI_Type_size​определяет "чистый" размер элемента некоторого типа (за вычетом
пустых промежутков).
Любой тип данных в MPI имеет две характеристики: протяженность и размер, выраженные в
байтах:

● Протяженность типа​определяет, сколько байт переменная данного типа занимает в


памяти. Эта величина может быть вычислена как:
адрес последней ячейки данных - адрес первой ячейки данных + длина последней
ячейки данных (опрашивается подпрограммой MPI_Type_extent).
● Размер типа​определяет количество реально передаваемых байт в коммуникационных
операциях. Эта величина равна сумме длин всех базовых элементов определяемого
типа (опрашивается подпрограммой MPI_Type_size).

Функция MPI_Type_extent​определяет протяженность элемента некоторого типа.


MPI_Aint​- array of displacements
MPI_ROW -
MPI_Type_commit​- Новый производный тип регистрируется вызовом функции
MPI_Type_commit. Только после регистрации новый производный тип можно использовать в
коммуникационных подпрограммах и при конструировании других типов.
Предопределенные типы MPI считаются зарегистрированными.

10.2​​Explicati ce problema rezolva acest program si argumentati raspunsul


Эта программа записывает в файл элементы матрицы? Еще непонятно т.к. программа пока не
работает

Основные функции, которые описаны в программах


​ PI_Init(int *argc, char ***argv) -​каждому процессу при инициализации передаются
M
аргументы функции main, полученные из командной строки.
MPI_Comm_rank(MPI_Comm comm, int *rank)​- Функция возвращает номер процесса,
вызвавшего эту функцию. Номера процессов лежат в диапазоне 0..size-1.
MPI_Comm_size(MPI_Comm comm, int *size)​- Функция возвращает количество процессов
в области связи коммуникатора comm.
int MPI_Finalize(void) - ​Функция закрывает все MPI-процессы и ликвидирует все области
связи.
int MPI_Reduce(void* sendbuf, void* recvbuf, int count,MPI_Datatype datatype, MPI_Op
op, int root, MPI_Comm comm) -​объединяет элементы входного буфера каждого процесса в
группе, используя операцию op , и возвращает объединенное значение в выходной буфер
процесса с номером root

5. Новый билет
5.1 Вычисляется общее количество процессов, сгенерированных узлами кластера.

Вам также может понравиться