Sumowanie elementów szeregu zbieżnego
-- Sebastian Pawlak, 2000.
Kod źródłowy pliku "main.c":
/* Program sumuje `MAX' elementow szeregu zbieznego przy uzyciu MPI_Reduce. * Program dziala w trybie point-to-point * s1222, 2000.03.19 * * Wykorzystane zostaly funkcje tworzace komunikator. * Proces 0 (master) zostanie wylaczony z MPI_COMM_WORLD i w ten * sposob zostanie wylaczony z obliczen (bedzie oczekiwal na wyniki * obliczen slave`ow). * * MPI_Reduce zbiera ze wszystkich procesow bufory dokonujac zadanej * operacji arytmetycznej / logicznej na odpowiadajacych sobie elementach * tych buforow - wynik operacji jest zwracany do bufora docelowego. * Funkcja uzywa algorytmu drzewiastego do zbierania wynikow. * * schemat zrownoleglenia laczenia buforow (wraz z wykonaniem zadanej * operacji arytmetycznej) za pomoca MPI_Reduce * * 0 1 2 3 4 5 6 7 * | | | | | | | | * |<----| |<----| |<----| |<----| * |op | |op | |op | |op | * | | | | | | | | * |<----------| | |<----------| | * |op | | | |op | | | * | | | | | | | | * |<----------------------| | | | * |op | | | | | | | * * zakladajac ze proces 0 posiada bufor[5] = { 5, 7, 2 ,1 ,0 }, natomiast * proces 1 posiada bufor[5] = { 2, 0, 5, 2, 8 }, * to proces 0 (root), dla zadanej operacji MPI_SUM * bedzie mail wynik[5] = { 7, 7, 7, 3, 8 }; * dostepne operacje: * MPI_MAX - Maximum, MPI_MIN - Minimum, * MPI_SUM - Sum, MPI_PROD - Product (mnozenie), * MPI_LAND - Logical AND, MPI_BAND - Bitwise AND, * MPI_LOR - Logica OR, MPI_BOR - Bitwise OR, * MPI_LXOR - Logical Exclusive OR, MPI_BXOR - Bitwise Exclusive OR, * MPI_MAXLOC - Maximum and Location of Maximum, * MPI_MINLOC - Minimum and Location of Minimum. */ #include <stdio.h> #include "mpi.h" #define MAX 3000000 int main(int argc, char **argv) { int rank, size; int i, xx, yy; MPI_Status status; double wynik, suma = 0; double startTime, endTime; MPI_Group staraGrupa, nowaGrupa; MPI_Comm nowyKomunikator; int procesWykluczany[] = { 0 }; /* master */ MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); /************************** * tworzenie komunikatora * **************************/ /* pobranie procesor nalezacych do grupy identyfikowanej przez komunikator MPI_COMM_WORLD */ MPI_Comm_group(MPI_COMM_WORLD, &staraGrupa); /* wykluczenie z otrzymanej grupy procesu numer 0 */ MPI_Group_excl(staraGrupa, 1, procesWykluczany, &nowaGrupa); /* tworzenie komunikatora na podstawie wyznaczonej nowej grupy */ MPI_Comm_create(MPI_COMM_WORLD, nowaGrupa, &nowyKomunikator); MPI_Comm_size(nowyKomunikator, &size); MPI_Comm_rank(nowyKomunikator, &rank); printf("rank: %d \n", rank); if(rank != 0 && rank != MPI_UNDEFINED) { /* nie master */ xx = (rank - 1) * (MAX / (size - 1)); yy = (rank) * (MAX / (size - 1)); for(i = xx; i < yy ; i++) suma += (1 / (double)(1 + i)); printf("suma czesciowa z procesu nr %d: %f\n", rank, suma); MPI_Reduce(&suma, &wynik, 1, MPI_DOUBLE, MPI_SUM, 0, nowyKomunikator); /* przesylanie `sum', wraz z dodawaniem, * do `wynik' w procesie 0 */ } else if(rank != MPI_UNDEFINED) { startTime = MPI_Wtime(); suma = 0; MPI_Reduce(&suma, &wynik, 1, MPI_DOUBLE, MPI_SUM, 0, nowyKomunikator); /* zbieranie wynikow od slaveow ; * master juz nie wysyla danych !!! */ endTime = MPI_Wtime(); printf("wynik: %f\n", wynik); printf("czas %f sek.\n", endTime - startTime); } /* MPI_Comm_free(nowyKomunikator); MPI_Group_free(&nowaGrupa); MPI_Group_free(&staraGrupa); */ MPI_Finalize(); return 0; }