MPI - ćwiczenia

Transkrypt

MPI - ćwiczenia
Optymalizacja z użyciem klastrów
obliczeniowych
MPI - ćwiczenia
Zadanie 1
Dana jest następująca funkcja f (i), której dziedziną są liczby całkowite dodatnie.
Chcemy się dowiedzieć dla ilu spośród liczb całkowitych j od 1 do 2 000 000 000
zachodzi własność: f (j) == c, gdzie liczba całkowita c jest zadana przez użytkownika, jako parametr wywołania programu. Badaną funkcję zdefiniowano następująco:
int f (int
int
int
for
i) {
i4_huge = 2147483647;
j, k, value = i;
(j = 1; j <= 5; j++) {
k = value / 127773;
value = 16807 * (value - k * 127773) - k * 2836;
if (value <= 0)
value = value + i4_huge;
}
return value;
}
Opracuj algorytm równoległy z wykorzystaniem biblioteki MPI. Przetestuj
swoje rozwiązanie uruchamiając program z wykorzystaniem 1, 2, 4 i 6 wątków.
Zadanie 2
Zaimplementuj równoległy algorytm zliczający wszystkie liczby pierwsze znajdujące się w przedziale pomiędzy zerem, a liczbą N wprowadzoną przez użytkownika. Przetestuj swoje rozwiązanie dla przynajmniej N = 107 . Wyświetl ile liczb
pierwszych udało Ci się znaleźć oraz oblicz sumę (o podstawie modulo równiej
123) dla wszystkich liczb pierwszych.
Zadanie 3
Zaimplementuj operację mnożenia dwóch

3
1 0 2 
· 2
−1 3 1
1
macierzy:

1
5 1

1 =
4 2
0
Wykorzystaj algorytm Cannona:
– dane są dwie macierze:


3 8 6
A = 7 1 6,
8 4 6


4 2 4
B = 1 8 6
4 2 7
– algorytm rozpoczynamy od tzw. „fazy przygotowawczej”. Tworzymy podmacierze A’, przesuwając rzędy macierzy A w kierunku mniejszych indeksów,
oraz B’, przesuwając kolumny macierzy B również w kierunku mniejszych
indeksów o numer rzędu/kolumny (zakładając, że numerujemy od 0):




3 8 6
4 8 7
A0 =  1 6 7  ,
B0 =  1 2 4 
6 8 4
4 2 6
– w K krokach dokonujemy przemnożenia wszystkich komórek pomiędzy macierzami A’ i B’, a następnie sumujemy otrzymane wyniki do macierzy tymczasowej (domyślnie wypełnionej zerami). Macierze A’ oraz B’ zostają podane kolejnym przesunięciom (tylko o jedną pozycję). Algorytm powtarzamy
do momentu, aż stan podmacierzy nie będzie taki sam, jak w fazie przygotowawczej:
• K =0

 
 
 

3 8 6
4 8 7
0 0 0
12 64 42
 1 6 7  ·  1 2 4  +  0 0 0  =  1 12 28 
6 8 4
4 2 6
0 0 0
24 16 24
• K =1

 
 
 
20 76 54
8 6 3
1 2 4
12 64 42
 6 7 1  ·  4 2 6  +  1 12 28  =  25 26 34 
56 48 66
4 8 7
24 16 24
8 4 6

• K =2

 
 
 

6 3 8
4 2 6
20 76 54
44 82 102
 7 1 6  ·  4 8 7  +  25 26 34  =  53 34 76 
4 6 8
1 2 4
56 48 66
60 60 98
Zadanie 4
Gra w życie toczy się na skończonej planszy (płaszczyźnie) podzielonej na kwadratowe komórki. Każda komórka ma ośmiu „sąsiadów”, czyli komórki przylegające do niej bokami i rogami. Każda komórka może znajdować się w jednym z
dwóch stanów: może być albo „żywa” (włączona), albo „martwa” (wyłączona).
Stany komórek zmieniają się krokowo. Stan wszystkich komórek w danym kroku
jest używany do obliczenia stanu wszystkich komórek w kroku następnym. Po
obliczeniu wszystkie komórki zmieniają swój stan dokładnie w tym samym momencie. Stan komórki zależy tylko od liczby jej żywych sąsiadów. W grze tej
nie ma graczy w dosłownym tego słowa znaczeniu. Udział człowieka sprowadza się jedynie do ustalenia stanu początkowego komórek. Zdefiniowano kilka
wzorców reguł generowania, najbardziej rozpowszechnione są reguły wymyślone
przez Conwaya (znanego brytyjskiego matematyka). W niniejszym zadaniu jednak przyjmiemy trochę inne reguły.
– Martwa komórka, która ma 1 lub 2 żywych sąsiadów, staje się żywa w następnym kroku (rodzisię),
– Żywa komórka z 1 albo 2 żywymi sąsiadami pozostaje nadal żywa; przy innej
liczbie sąsiadów umiera (z „samotności” albo „zatłoczenia”).
Napisz program równoległy (podobnie jak w przypadku innych ćwiczeń w języku
C++ oraz modelu z przesyłaniem wiadomości) symulujący dwuwymiarowy binarny automat komórkowy do gry w życie. Przyjmij, że gra rozgrywa się w
macierzy 8000 wierszy na 8000 kolumn, która na początku (w kroku 0) ma włączone komórki na obu przekątnych, a pozostałe ma wyłączone. Jaka będzie liczba
włączonych komórek w kroku 400?