Сумма массива с использованием MPI
Предварительное условие: MPI - Распределенные вычисления стали проще
Интерфейс передачи сообщений (MPI) - это библиотека процедур, которые можно использовать для создания параллельных программ на C или Fortran77. Он позволяет пользователям создавать параллельные приложения, создавая параллельные процессы и обмениваясь информацией между этими процессами.
MPI использует две основные процедуры связи:
- MPI_Send , чтобы отправить сообщение другому процессу.
- MPI_Recv , чтобы получить сообщение от другого процесса.
Синтаксис MPI_Send и MPI_Recv:
int MPI_Send (void * data_to_send, int send_count, MPI_Datatype send_type, int destination_ID, int тег, MPI_Comm comm); int MPI_Recv (недействительно * полученные_данные, int receive_count, MPI_Datatype receive_type, int sender_ID, int тег, MPI_Comm comm, MPI_Status * статус);
Чтобы уменьшить временную сложность программы, параллельное выполнение подмассивов выполняется параллельными процессами, работающими для вычисления их частичных сумм, а затем, наконец, главный процесс (корневой процесс) вычисляет сумму этих частичных сумм, чтобы вернуть общую сумму массив.
Примеры:
Ввод: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} Выход: сумма массива 55 Ввод: {1, 3, 5, 10, 12, 20, 4, 50, 100, 1000} Выход: сумма массива 1205
Примечание. Для выполнения следующей программы в вашей системе Linux должен быть установлен MPI. Для получения подробной информации, пожалуйста, обратитесь к MPI - Упрощение распределенных вычислений.
Скомпилируйте и запустите программу, используя следующий код:
mpicc имя_программы.c -o файл_объекта mpirun -np [количество процессов] ./object_file
Ниже приведена реализация указанной выше темы:
#include <mpi.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> // size of array #define n 10 int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // Temporary array for slave process int a2[1000]; int main( int argc, char * argv[]) { int pid, np, elements_per_process, n_elements_recieved; // np -> no. of processes // pid -> process id MPI_Status status; // Creation of parallel processes MPI_Init(&argc, &argv); // find out process ID, // and how many processes were started MPI_Comm_rank(MPI_COMM_WORLD, &pid); MPI_Comm_size(MPI_COMM_WORLD, &np); // master process if (pid == 0) { int index, i; elements_per_process = n / np; // check if more than 1 processes are run if (np > 1) { // distributes the portion of array // to child processes to calculate // their partial sums for (i = 1; i < np - 1; i++) { index = i * elements_per_process; MPI_Send(&elements_per_process, 1, MPI_INT, i, 0, MPI_COMM_WORLD); MPI_Send(&a[index], elements_per_process, MPI_INT, i, 0, MPI_COMM_WORLD); } // last process adds remaining elements index = i * elements_per_process; int elements_left = n - index; MPI_Send(&elements_left, 1, MPI_INT, i, 0, MPI_COMM_WORLD); MPI_Send(&a[index], elements_left, MPI_INT, i, 0, MPI_COMM_WORLD); } // master process add its own sub array int sum = 0; for (i = 0; i < elements_per_process; i++) sum += a[i]; // collects partial sums from other processes int tmp; for (i = 1; i < np; i++) { MPI_Recv(&tmp, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status); int sender = status.MPI_SOURCE; sum += tmp; } // prints the final sum of array printf ( "Sum of array is : %d
" , sum); } // slave processes else { MPI_Recv(&n_elements_recieved, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); // stores the received array segment // in local array a2 MPI_Recv(&a2, n_elements_recieved, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); // calculates its partial sum int partial_sum = 0; for ( int i = 0; i < n_elements_recieved; i++) partial_sum += a2[i]; // sends the partial sum to the root process MPI_Send(&partial_sum, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); } // cleans up all MPI state before exit of process MPI_Finalize(); return 0; } |
Выход:
Сумма массива 55
Ниже приведен снимок процессов, вычисляющих свои частичные суммы: