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;
}





