Skocz do zawartości
shooter

Mpi

Rekomendowane odpowiedzi

Można uruchomić MPI w trybie emulacji, wtedy dowolna liczba procesorów (komputerów) jest emulowana jako wątki, od systemu zależy jak te wątki zostaną ewentualnie na dwa procesory porozdzielane. Dodatkowo MPI zapewnia, że taka emulacja na wątkach nie jest deterministyczna, tzn za każdym uruchomieniem można się spodziewać innego przeplotu wątków i innych czasów przydzielonych dla poszczególnych wątków, dzięki temu bardziej realistycznie jest emulowana sieć i praca na wielu komputerach.

Edytowane przez Ragnor

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Do uruchamianie programów używałem MPICH 2 (implementuje MPI 1 i 2), jest dostępny też pod windowsa, więc lokalnie można wszelkie testy przeprowadzać. Posiada on bogatą dokumentacje więc nie powinno być problemu z rozszyfrowaniem co i jak.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Gdy tego uzywam nie moge sie polaczyc ze swoim komputerem, lol. Aby uruchomic program w MPI nalezy to robic przez inny program dostarczony z biblioteka. W tym programie wyskakuje mi komunikat, ze nie mozna sie polaczyc z komputerem

Używasz tego programu lokalnie? Opisz dokładnie krok po kroku co robisz i jakie dokładnie komunikaty dostajesz.

Z tego co pamiętam MPICH2 wymaga konta (usera) i odpowiedniego hasła aby uruchomić dane zadania w systemie. Ja na te potrzeby w windowsie stworzyłem nowego usera (z prawami admina) i go zarejestrowałem w mpi, wcześniej miałem tylko domyślnego użytkownika. Dopiero po takim triku MPICH2 dobrze pracował.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Wchodze do katalogu w MPICH2/bin i odpalam program MPIexec wrapper. podaje mu sciezke do przykladu - MPICH2/examples/cpi.exe i klikam execute. Wyskakuje mi komunikat: Unable to connect "i tu nazwa mojego kompa". Jesli mozesz to opisz co nalezy zrobic i czy kazda aplikacje nalezy odpalac przez tego wrappera? Czyli na dwoch jajkach mozna oszukac MPI i zademonstrowac na jednym kompie? Z gory wielkie dzieki za wszystko.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Tak jak wspomniałem wcześniej w windowsie utwórz nowe konto użytkownika (z prawami administratora) np. test i obowiązkowo z hasłem np. test. Następnie uruchom wmpiregister i podaj tam nazwę użytkownika i jego hasło a następnie daj register. Teraz sprawdź jak zachowa się przykład cpi.exe.

Aplikacje nie trzeba odpalać przez ten okienkowy program, w labelce ShowCommand widnieje odpowiadające polecenie konsolowe za pomocą jakiego możesz odpalić program w mpi z pominięciem tego gui.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Chodzi mi jeszcze o implementacje. Przyklad dziala, ale nie moge zlinkowac programu, gryz wyskakuje błąd: mpi.obj : error LNK2019: unresolved external symbol "void __cdecl MPI::Init(int &,char * * &)" (?Init@MPI@@YAXAAHAAPAPAD@Z) referenced in function _main.

Moglbys napisac jak implementowales MPI?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Z implementacją sobie poradziłem. Komendy MPI dzialaja. Mam teraz problem - zrownoleglic w MPI eliminacje Gaussa. W openMP jeszcze jakos bym to napisal ale w MPI ciezko. Oto Gauss:

int partial_pivoting(double **m, int size, int a){	double max=m[a][a];	double tmp;	int index;	bool zm=false;	for (int i=1; i<size-a; i++)	 if(fabs(m[a+i][a])>max)	 {	   max=fabs(m[a+i][a]);	   index=a+i;		zm=true;	 }	 			for(int i=a; i<=size-a; i++) //zamiana wierszy	{	  tmp=m[a][i];	  m[a][i]=m[index][i];	  m[index][i]=tmp;	}      if(zm)	 return 0;      else	 return 1;}//////////////////////////////////////////////////////////////////////////////////Gaussvoid gauss(double** m, int size){   double alfa;      for(int k=0; k<size; k++)   {		for(int i=k+1; i<size; i++)		{  		 if(m[k][k] == 0)			if(partial_pivoting(m, k, size))			{ 			  cout << endl << "Macierz jest osobliwa." << endl;			   break;			}		  		  alfa = m[i][k] / m[k][k];		   		   for(int j=k; j<=size; j++)			m[i][j] = m[i][j] - alfa * m[k][j];				}     }	  }

chodzi o zrownoleglenie samej funkcji Gauss. Masz moze pomysł jak to rozpracować z MPI?

Edytowane przez shooter

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Wymyśliłem coś takiego. Pewnie nie do końca poprawne, ale ...

//Gauss

void gauss(double** m, int size){   double alfa;     for(int k=0; k<size; k++)   {		for(int i=k+1; i<size; i++)		{  		 if(m[k][k] == 0)			if(partial_pivoting(m, k, size))			{			  cout << endl << "Macierz jest osobliwa." << endl;			   break;			}		  		  alfa = m[i][k] / m[k][k];		  			  #pragma omp parallel sections		   {		  			 #pragma omp section			 {		   			 for(int j=k; j<=size; j+=2)			  m[i][j] = m[i][j] - alfa * m[k][j];					  }			  #pragma omp section			  {			  for(int j=k+1; j<=size; j+=2)			   m[i][j] = m[i][j] - alfa * m[k][j];   			   }		   		   }			}     }	  }

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Na OpenMP nie znam się ale z tego co widzę, ten algorytm jest zrównoleglony tylko do 2 maszyn, mam racje? Interesuje Cię zrównoleglenie algorytmu na konkretną liczbę maszyn/procesów powiedzmy 2,4,8 czy też na jakąś dowolną liczbę: p (gdzie p zależne od 'size')?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeśli chcesz to napisać z wykorzystaniem MPI to musisz trochę zmienić podejście do problemu. W MPI każdy proces może działać na osobnej mazynie, więc nie ma czegoś takiego jak wspólna pamięc (w szczególności każdy proces będzie miał własną macierz/tablicę z danymi). Aby wymienić informacje, wyniki między procesami, trzeba je jawnie wysłać do innego (lub wszystkich) procesów oraz w danych procesach je odebrać. Procesy mogą być uruchamiane na różnych pod względem konfiguracji maszynach, więc należy zadbać o synchronizacje obliczeń, tak aby szybsza maszyna czekała na zakończenie obliczeń na wolniejszej. Jako że dane są przesyłane przez sieć, trzeba minimalizować liczbę rozmów między procesami, gdyż to można zabić cały zysk z zrównoleglenia algorytmu.

Na początku zapoznaj się z takimi funkcjami MPI jak MPI_send, MPI_receiv, MPI_geather itd.. poznaj do czego służą, zwykle mają one dużo parametrów ale ważne są może 2,3 ;), reszte wstawia się prawię zawsze taką samą.

W MPI dla uproszczenia struktury algorytmu często zakłada się, że jeden z procesów koordynuje działanie innych jest tzw. 'masterem', zwykle się przyjmuje, że jest to proces numer 0, inne procesy to tzw 'workerzy'.

Co do algorytmu to można do niego podejść tak, że najbardziej wewnętrzną pętle możesz tak wykonać (pseudokod):

alfa = m[i][k] / m[k][k];if (moj_numer == 0) {  for(int j=k; j<=size; j+=2) {	   m[i][j] = m[i][j] - alfa * m[k][j];		   }   wyślij własne przeliczone dane do procesu 1   odbierz przeliczone dane z procesu 0   dodaj odebrane dane do własnej tablicy m} else { // zakładam że są tylk 2 procesy    for(int j=k+1; j<=size; j+=2)	   m[i][j] = m[i][j] - alfa * m[k][j];    }  odbierz przeliczone dane z procesu 1  wyślij własne przeliczone dane do procesu 0  dodaj odebrane dane do własnej tablicy m}

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Szanowny Ragnorze. Napisalem kod w MPI, dziala dla 1 procesu, ale nie chce dla wiekszej ilosci. Co jest nie tak? Bardzo prosze o porade. Wydaje mi sie, ze cos jest nie tak z MPI_Status.

 

#include <cstdlib>#include <iostream>#include "matrix.h"#undef SEEK_SET#undef SEEK_END#undef SEEK_CUR#include <MPI/mpi.h>void senddata(double** a, double* b, int rank, int size, int msize, MPI_Status status){   int i;	 if(rank == 0)	 {		for(i = 0;i < msize;i++)		{			if(i % size == 0) continue;						a[i][msize] = b[i];			MPI_Send(a[i],msize+1,MPI_DOUBLE,(i % size),0, MPI_COMM_WORLD);			MPI_Send(&(b[i]),1,MPI_DOUBLE,(i % size),0, MPI_COMM_WORLD);		}	 }	 else	 {		for(i = 0;i < msize;i++)		{			if(i % size != rank) continue;						MPI_Recv(a[i],msize+1,MPI_DOUBLE,0,0, MPI_COMM_WORLD, &status);			MPI_Recv(&(b[i]),1,MPI_DOUBLE,0,0, MPI_COMM_WORLD, &status);			b[i] = a[i][msize];		}	 }}void senddataback(double** a, double* b, int rank ,int size, int msize, MPI_Status status){	int i;	if(rank == 0)	{		for(i = 0;i < msize;i++)		{			if(i % size == 0) continue;			b[i] = a[i][msize];						MPI_Recv(a[i],msize+1,MPI_DOUBLE, (i % size), 0, MPI_COMM_WORLD, &status);			MPI_Recv(&(b[i]),1,MPI_DOUBLE,(i % size), 0, MPI_COMM_WORLD, &status);		}	}	else	{		for(i = 0;i < msize;i++)		{			if(i % size != rank) continue;			MPI_Send(a[i],msize+1,MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);			MPI_Send(&(b[i]),1,MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);			a[i][msize] = b[i];		}	}}void eliminate(double** a , double* b, int rank ,int size, int msize){	int i,j,k;	for(k = 0; k < msize;k++)	{		if(k % size == rank)		{			if(a[k][k] == 0)			{				cout <<"dzielenie przez 0";				MPI_Finalize();				exit(0);			}						/* prepare my row */			for(j = k + 1;j < msize;j++)			{				a[k][j] = a[k][j]/a[k][k];			}			b[k] = b[k]/a[k][k];			a[k][k] = 1;			/* end prepare */			a[k][msize] = b[k];			MPI_Bcast(a[k],msize+1,MPI_DOUBLE, rank, MPI_COMM_WORLD);						for(i = k + 1;i < msize;i++)			{				if(i % size != rank)continue;								for(j = k + 1;j < msize;j++)				{					a[i][j] = a[i][j] - a[i][k] * a[k][j];				}								b[i] = b[i] - a[i][k] * b[k];				a[i][k] = 0;			}		}		else		{			MPI_Bcast(a[k],msize+1,MPI_DOUBLE,k % size, MPI_COMM_WORLD);			MPI_Bcast(&(b[k]),1,MPI_DOUBLE,k % size, MPI_COMM_WORLD);			b[k] = a[k][msize];			for(i = k + 1;i < msize;i++)			{				if(i % size != rank)continue;				for(j = k + 1;j < msize;j++)				{					a[i][j] = a[i][j] - a[i][k] * a[k][j];				}				b[i] = b[i] - a[i][k] * b[k];				a[i][k] = 0;			}		}	}}void backward(double** a, double* b, int msize){	int i,j,k;	for(i = msize-1;i >= 0;i--)	{		for(k = i+1;k < msize;k++)		{			b[i] = b[i] - a[i][k];		}		for(j = i - 1;j >= 0;j--)		{			a[j][i] = a[j][i] * b[i];		}	}}int main( int argc, char *argv[] ){   int id_proc, num_procs;   int size;  //rozmiar macierzy   double wtime1, wtime2;  	size = 1500;  double** m;    double* V;       		MPI_Init(&argc,&argv);   MPI_Comm_size(MPI_COMM_WORLD,&num_procs);	MPI_Comm_rank(MPI_COMM_WORLD,&id_proc); 	MPI_Status status;		if(id_proc == 0)	{	   m = new double* [size];					   	   V = new double [size];   			 for(int i=0; i<size; i++)		  m[i] = new double[size];	   	 for (int i=0; i<size; i++)	  for(int j=0; j<size+1; j++)		m[i][j] = 1+rand()%10; 	 }	 	 	MPI_Bcast(&size, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);		if(id_proc != 0)	{			   	m = new double* [size];					   	   V = new double [size];   			 for(int i=0; i<size; i++)		  m[i] = new double[size];			   			   	}			senddata(m, V, id_proc, num_procs, size, status);	eliminate(m, V, id_proc, num_procs, size);	senddataback(m, V, id_proc, num_procs, size, status);	backward(m, V, size);	MPI_Finalize();	//system("PAUSE");	return 0;}
Edytowane przez shooter

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Widzę, że kodu trochę jest, ale w tej chwili łatwiej mi będzie odnaleźć błąd, jeśli zamiast analizować kod, opiszesz mi modelowo jak przebiega cały program i jak komunikują się ze sobą procesy. Z tego co zauważyłem program nie ma ograniczenia do 2 procesów.

Dla przykładu jakie zadanie ma ten wiersz kodu w programie (w metodzie main):

MPI_Bcast(&size, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

z tego co widzę size jest typu int a nie double, a do tego nikt tego komunikatu nigdzie nie odbiera (możliwe ,że w tym momencie, gdy program ma więcej niż 2 procesy to po prostu się blokuje).

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie


×
×
  • Dodaj nową pozycję...