WWW. http://www.netlib.org/pvm3/book/pvm-book.html. http://www.netlib.org/pvm3/index.html. http://www.netlib.org/pvm3/pvm3.4.5.tgz



Podobne dokumenty
Środowiska przetwarzania rozproszonego

Parallel Virtual Machine

Podstawy komunikacji między procesami PVM

Pierwsze kroki w środowisku PVM

Łamanie haseł. Zakres ćwiczenia. Przedstawienie problemu. Zadanie do samodzielnego wykonania

Pobieranie argumentów wiersza polecenia

Zegary logiczne. Zakres ćwiczenia. Problem rozbieżności czasów. Koncepcja programu. Przygotowanie programu

Sieciowa komunikacja procesów - XDR i RPC

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

Programowanie Proceduralne

Zaawansowane operacje grupowe

PVM Parallel Virtual Machine

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Shared memory and messages. Functions. process 0. process 1. program 0. program 0. data 0. data 1. program 1. data 0. data 1.

Programowanie proceduralne INP001210WL rok akademicki 2015/16 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Mechanizmy komunikacji grupowej w bibliotece PVM

Programowanie w modelu przesyłania komunikatów specyfikacja MPI. Krzysztof Banaś Obliczenia równoległe 1

r 2r Rysunek 1 Koło wpisane w kwadrat

Biblioteka standardowa - operacje wejścia/wyjścia

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

Obsługa plików. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 25 września 2011

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Literatura uzupełniająca: W. Richard Stevens, Programowanie zastosowań sieciowych w systemie Unix WNT 1998

Programowanie Równoległe Wykład 4. MPI - Message Passing Interface. Maciej Matyka Instytut Fizyki Teoretycznej

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

Uzupełnienie dot. przekazywania argumentów

dynamiczny przydział pamięci calloc() memset() memcpy( ) (wskaźniki!! )

Zdalne wywołania procedur. Jarosław Kuchta Programowanie Współbieżne

1. Ustanawianie ograniczeń na użycie zasobów

Podstawy programowania w języku C++

Gniazda BSD. komunikacja bezpołączeniowa

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

3. Identyfikacja. SKŁADNIA #include <sys/socket.h> int getpeername(int socket, struct sockaddr *addr, int *addrlen);

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

Czy procesor musi się grzać?

Laboratorium Podstawy Przetwarzania Rozproszonego SPRAWOZDANIE z zadania SERWIS KOMPUTEROWY

Wstęp do Programowania, laboratorium 02

PVM. Luděk Matyska. Jaro Fakulta informatiky MU. Luděk Matyska (FI MU) PVM Jaro / 19

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

WYKŁAD 10. Zmienne o złożonej budowie Statyczne i dynamiczne struktury danych: lista, kolejka, stos, drzewo. Programy: c5_1.c, c5_2, c5_3, c5_4, c5_5

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Co nie powinno być umieszczane w plikach nagłówkowych:

۰ Elementem jednostkowym takiego pliku jest bajt. ۰ Format pliku binarnego: [bajty pliku][eof]

Wstęp do programowania 1

Informatyka. Wy-03 Dynamiczna alokacja pamięci, wyjątki. mgr inż. Krzysztof Kołodziejczyk

Programowanie procesorów graficznych w CUDA.

Procesy. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 9 października 2011

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Stałe i zmienne znakowe. Stała znakowa: znak

Programowanie Równoległe i Rozproszone

Krótkie wprowadzenie do korzystania z OpenSSL

SQL 4 Structured Query Lenguage

Instytut Teleinformatyki

RPC. Zdalne wywoływanie procedur (ang. Remote Procedure Calls )

Tablice w argumentach funkcji. Tablicy nie są przekazywane po wartości Tablicy są przekazywane przez referencje lub po wskaźniku

Tworzenie aplikacji w języku Java

Nazwy programów, polece, katalogów, wyniki działania wydawanych polece.

Łącza nienazwane(potoki) Łącza nienazwane mogą być używane tylko pomiędzy procesami ze sobą powiązanymi.

Aplikacja Sieciowa. Najpierw tworzymy nowy projekt, tym razem pracować będziemy w konsoli, a zatem: File->New- >Project

Lab 8. Tablice liczbowe cd,. Operacje macierzowo-wektorowe, memcpy, memmove, memset. Wyrażenie warunkowe.

Bazy danych 10. SQL Widoki

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Języki i metodyka programowania. Wprowadzenie do języka C

Funkcje zawarte w bibliotece < io.h >

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

Podstawy Programowania.

Funkcje zawarte w bibliotece < io.h >

Oprogramowanie i wykorzystanie stacji roboczych. Wykład 4

Język ANSI C. część 11. Jarosław Gramacki Instytut Informatyki i Elektroniki

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Signals + Threads: Qt vs. Boost

Wstęp do programowania

Wykład 5_2 Algorytm ograniczania liczby serii za pomocą kopcowego rozdzielania serii początkowych

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Tablice, funkcje - wprowadzenie

PARADYGMATY PROGRAMOWANIA Wykład 4

Obsługa plików Procesy

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Instrukcja konfiguracji usługi Wirtualnej Sieci Prywatnej w systemie Mac OSX

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

I - Microsoft Visual Studio C++

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Functionalization. Jeszcze o funkcjach i strukturze projektu. Marcin Makowski. 3 grudnia Zak lad Chemii Teoretycznej UJ

Podstawy Programowania

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Struktury. Przykład W8_1

SYSTEMY CZASU RZECZYWISTEGO - VxWorks

KURS C/C++ WYKŁAD 8. Deklaracja funkcji informuje komplilator jaką wartość funkcja będzie zwracała i jakiego typu są jej argumenty.

Programowanie współbieżne... (4) Andrzej Baran 2010/11

Wskaźniki. Informatyka

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Transkrypt:

WWW http://www.netlib.org/pvm3/book/pvm-book.html http://www.netlib.org/pvm3/index.html http://www.netlib.org/pvm3/pvm3.4.5.tgz PVM p. 1

instalowanie 1. Sprowadzić: http://www.netlib.org/pvm3/pvm3.4.5.tgz 2. Rozpakować: $ tar zxvf pvm3.4.5.tgz 3. Dodać do.bashrc PVM_ROOT=$HOME/pvm3 export PVM_ROOT 4. Wkleić do.bashrc zawartość pvm3/lib/bashrc.stub 5. Dodać do.bashrc coś w stylu: export PVM_RSH=/usr/bin/ssh 6. W kartotece pvm3/ wywołać: make PVM p. 2

uruchamianie Uruchomienie interaktynej konsoli oraz demona pvmd na danej maszynie: $ pvm Polecenia w konsoli pvm: help - drukuje listę poleceń add - dodaje nowy host do maszyny wirtualnej (uruchamia na nim demona pvmd) conf - wypisuje kofigurację maszyny wirtualnej delete - usuwa host z maszyny wirtualnej quit - wyjście z terminala (ale pvmd pozostaje uruchomiony) halt - zatrzymuje demony pvmd... PVM p. 3

kompilacja przykładów $ cd $PVM_ROOT/examples $ aimk hello ( aimk polecenie podobne do make dla programów pvm) $ aimk hello_other $ $PVM_ROOT/bin/LINUX/hello (Programy binarne powinny być w tym katalogu na każdej maszynie wchodzącej w skład maszyny wirtualnej) Dobrze jest umieszczać katalogi z własnymi kodami źródłowymi w miejscu gdzie jest katalog examples/, skopiować do nich i zmodyfikować na własne potrzeby plik $PVM_ROOT/examples/Makefile.aimk. PVM p. 4

hello.c #include <stdio.h> #include "pvm3.h" main() { int cc, tid; char buf[100]; printf("i m t%x\n", pvm_mytid()); cc = pvm_spawn("hello_other", (char**)0, 0, "", 1, &tid); if (cc == 1) { cc = pvm_recv(-1, -1); pvm_bufinfo(cc, (int*)0, (int*)0, &tid); pvm_upkstr(buf); printf("from t%x: %s\n", tid, buf); //... PVM p. 5

hello.c } else printf("can t start hello_other\n"); pvm_exit(); exit(0); } PVM p. 6

hello_other.c #include "pvm3.h" main() { int ptid; char buf[100]; ptid = pvm_parent(); strcpy(buf, "hello, world from "); gethostname(buf + strlen(buf), 64); pvm_initsend(pvmdatadefault); pvm_pkstr(buf); pvm_send(ptid, 1); pvm_exit(); exit(0); } PVM p. 7

Interfejs programisty procedury dotępne dla programisty w języku C: plik nagłówkowy: $PVM_ROOT/include/pvm3.h biblioteki: $PVM_ROOT/lib/LINUX/libpvm3.a $PVM_ROOT/lib/LINUX/libgpvm3.a PVM p. 8

pvm_mytid int tid = pvm_mytid( void ) Zwraca task identifier danego procesu. Wartość < 0 -- błąd. Często używany aby wpisać się na listę procesów używanych przez PVM. PVM p. 9

pvm_exit int info = pvm_exit( void ) Informuje lokalnego pvmd, że proces opuszcza PVM. (Musi być wywołane przez proces, który nie był utworzony przez pvm_spawn. PVM p. 10

pvm_spawn int numt = pvm_spawn(char *task, char **argv, int flag, char *where, int ntask, int *tids ) Uruchomienie nowych procesów przez dany proces. task - nazwa pliku wykonywalnego (defaultowo na $HOME/pvm3/bin/$PVM_ARCH/) argv - wskaźnik do tablicy agrumentów zakończonej NULLem. (nie zawiera nazwy pliku wykonywalnego) (może być =NULL) PVM p. 11

pvm_spawn flag - suma wybranych opcji: PvmTaskDefault 0 PVM can choose any machine to start task PvmTaskHost 1 where specifies a particular host PvmTaskArch 2 where specifies a type of architecture PvmTaskDebug 4 Start up processes under debugger PvmTaskTrace 8 Processes will generate PVM trace data. PvmMppFront 16 Start process on MPP front-end. PvmHostCompl 32 Use complement host set PVM p. 12

pvm_spawn where - gdzie uruchomić (znaczenie zależy od opcji flag) ntask - liczba elementów tids tids - tablica długości ntask, w której zwrócone będą TIDy uruchomionych procesów lub błędy. numt - zwracana wartość: liczba faktycznie uruchomionych procesów. PVM p. 13

pvm_kill int info = pvm_kill( int tid ) Zabija proces tid (wysyła SIGTERM). Zwraca 0 lub <0 jeśli błąd. (Nie przeznaczony do samobójstwa - należy wykonać pvm_exit() i exit().) PVM p. 14

pvm_catchout #include <stdio.h> int info = pvm_catchout( FILE *ff ) Po wykonaniu tej procedury wyjście (stdout, stderr) zebrane z utworzonych (spawned) zadań trafia do pliku. ff - deskryptor pliku. info - status (<0 - błąd.) Identyfikatory procesów też mogą być wypisywane (opcja PvmShowTids w pvm_setopt) PVM p. 15

pvm_parent int tid = pvm_parent( void ) tid - identyfikator rodzica lub PvmNoParent - jeśli proces był utworzony przez pvm_spawn. PVM p. 16

pvm_tidtohost int dtid = pvm_tidtohost( tid ) tid - TID zadania dtid - TID demona na hoscie, na którym jest to zadanie. PVM p. 17

pvm_config int info = pvm_config( int *nhost, int *narch, struct pvmhostinfo **hostp ) struct pvmhostinfo { int hi_tid; char *hi_name; char *hi_arch; int hi_speed; }; nhost - zwrócona liczba hostów narch - zwrócona liczba formatów danych hostp - zwrócony wskaźnik do tablicy opisującej hosty maszyny wirtualnej. PVM p. 18

pvm_tasks int info = pvm_tasks( int where, int *ntask, struct pvmtaskinfo **taskp ) struct pvmtaskinfo { int ti_tid; // TID int ti_ptid; // parent TID int ti_host; // chyba DTID pvmd... int ti_flag; char *ti_a_out; // nazwa (tylko dla spawned ) } taskp; where - rodzaj zapytania: 0 for all the tasks on the virtual machine pvmd tid for all tasks on a given host tid for a specific task ntask - zwrócona liczba zadań taskp - zwrócony wskaźnik do tablicy z opisami PVM p. 19

pvm_addhosts int info = pvm_addhosts( char **hosts, int nhost, int *infos ) hosts - tablica nazw hostów (z opcjami) do dodania nhost - długośc hosts infos - tablica wyników (TIDy lub wartości <0 - błedy). info - ilość sukcesów PVM p. 20

pvm_delhosts int info = pvm_delhosts( char **hosts, int nhost, int *infos ) hosts - tablica nazw hostów (z opcjami) do dodania nhost - długośc hosts infos - tablica wyników (TIDy lub wartości <0 - błedy). info - ilość sukcesów PVM p. 21

pvm_sendsig int info = pvm_sendsig( int tid, int signum ) Wysyła sygnał signum do zadania tid. PVM p. 22

pvm_notify int info = pvm_notify( int what, int msgtag, int cnt, int *tids ) what - PvmTaskExit Task exits or is killed PvmHostDelete Host is deleted or crashes PvmHostAdd New host is added PvmNotifyCancel odwołanie (zorowane z oryginalnym what) cnt - dla PvmTaskExit i PvmHostDelete, długość tids dla PvmHostAdd, ile razy powiadamiać tids - dla PvmTaskExit i PvmHostDelete, tablica interesujących nas TIDów. dla PvmHostAdd, nieużywane. msgtag - etykieta dla komunikatów z powiadomieniami. PVM p. 23

pvm_setopt int oldval = pvm_setopt( int what, int val ) Może ustawić dużo różnych opcji. np. pvm_setopt( PvmRoute, PvmRouteDirect ); PVM p. 24

pvm_initsend int bufid = pvm_initsend( int encoding ) Czyści bufer do wysyłania i przygotowuje na zapakowanie nowych danych. encoding - PvmDataDefault 0 XDR PvmDataRaw 1 no encoding PvmDataInPlace 2 data left in place bufid - zwracany identyfikator bufora lub <0 błąd PVM p. 25

pvm_mkbuf int bufid = pvm_mkbuf( int encoding ) Tworzy nowy bufor do wysyłania. (Zwykle niepotrzebne.) encoding - PvmDataDefault 0 XDR PvmDataRaw 1 no encoding PvmDataInPlace 2 data left in place bufid - zwracany identyfikator bufora lub <0 błąd PVM p. 26

pvm_freebuf int info = pvm_freebuf( int bufid ) Zwalnia pamięć bufora bufid utworzonego przez pvm_mkbuf. (Bufory mogą być tworzone przez pvm_mkbuf, pvm_initsend, and pvm_recv.) PVM p. 27

pvm_getsbuf itp. int bufid = pvm_getsbuf( void ) int bufid = pvm_getrbuf( void ) int oldbuf = pvm_setsbuf( int bufid ) int oldbuf = pvm_setrbuf( int bufid ) zwracają/ustawiają buforów wysyłania i odbioru identyfikatory aktywnych PVM p. 28

pakowanie danych int info = pvm_pkbyte( char *xp, int nitem, int stride ) int info = pvm_pkcplx( float *cp, int nitem, int stride ) int info = pvm_pkdcplx( double *zp, int nitem, int stride ) int info = pvm_pkdouble( double *dp, int nitem, int stride int info = pvm_pkfloat( float *fp, int nitem, int stride ) int info = pvm_pkint( int *ip, int nitem, int stride ) int info = pvm_pkuint( unsigned int *ip, int nitem, int str int info = pvm_pkushort( unsigned short *ip, int nitem, int int info = pvm_pkulong( unsigned long *ip, int nitem, int s int info = pvm_pklong( long *ip, int nitem, int stride ) int info = pvm_pkshort( short *jp, int nitem, int stride ) int info = pvm_pkstr( char *sp ) PVM p. 29

pakowanie danych nitem - ile elementów zapakować stride - co który wybierać xp - wskaźnik do początku bloku bajtów cp, zp, dp, fp, ip, - analogicznie dla innytch typów PVM p. 30

pakowanie danych int info = pvm_packf( const char *fmt,... ) Podbny opis formatu jak w printf PVM p. 31

pvm_send int info = pvm_send( int tid, int msgtag ) Wysyła komunikat umieszczony w buforze wysyłania. tid - adresat msgtag - etykieta komunikatu (>=0) info - status wykonania pvm_send jest asynchroniczne (nieblokujące) PVM p. 32

pvm_mcast int info = pvm_mcast( int *tids, int ntask, int msgtag ) Wysyła wiadomość do tablicy tids. (Ale nie do nadawcy) PVM p. 33

pvm_recv int bufid = pvm_recv( int tid, int msgtag ) Blokuje wykonanie aż nadejdzie komunikat z etykietą msgtag od zadania tid. Umieszcza otrzymane dane w nowym aktywnym buforze odbierania. Zwraca identyfikator nowego aktywnego bufora odbierania. PVM p. 34

pvm_nrecv int bufid = pvm_nrecv( int tid, int msgtag ) Sprawdza czy nadeszła wiadomość z etykietą msgtag od zadania tid. Jeśli nadeszła to umieszcza w nowym aktywnym buforze i zwraca jego bufid. W przeciwnym razie zwraca 0. wildcard: -1 PVM p. 35

pvm_probe int bufid = pvm_probe( int tid, int msgtag ) Sprawdza ale nie odbiera wiadomości. Przed odebraniem można sprawdzić: pvm_bufinfo PVM p. 36

pvm_trecive #include <sys/time.h> int bufid = pvm_trecv( int tid, int msgtag, struct timeval *tmout ) wersja z timeoutem PVM p. 37

rozpakowywanie int info = pvm_unpackf( const char *fmt,... ) int info = pvm_upkbyte( char *xp, int nitem, int stride) int info = pvm_upkcplx( float *cp, int nitem, int stride) int info = pvm_upkdcplx( double *zp, int nitem, int stride) int info = pvm_upkdouble( double *dp, int nitem, int stride int info = pvm_upkfloat( float *fp, int nitem, int stride) int info = pvm_upkint( int *ip, int nitem, int stride) int info = pvm_upkuint( unsigned int *ip, int nitem, int st int info = pvm_upkushort( unsigned short *ip, int nitem, in int info = pvm_upkulong( unsigned long *ip, int nitem, int int info = pvm_upklong( long *ip, int nitem, int stride) int info = pvm_upkshort( short *jp, int nitem, int stride) int info = pvm_upkstr( char *sp ) PVM p. 38

grupy int inum = pvm_joingroup( char *group ) group - nazwa grupy inum - zwracany instance number (numer zadania w danej grup int info = pvm_lvgroup( char *group ) PVM p. 39

grupy int tid = pvm_gettid( char *group, int inum ) Zwraca tid zadania o instance number inum w grupie group. int inum = pvm_getinst( char *group, int tid )... int size = pvm_gsize( char *group ) aktualny rozmiar grupy PVM p. 40

pvm_bcast int info = pvm_bcast( char *group, int msgtag ) wysyła zawartośc aktywnego bufora wysyłania do całej grupy (poza nadawcą). nadawca nie musi być członkiem grupy. PVM p. 41

pvm_barrier info = pvm_barrier( char *group, int count ) Blokuje wywołujący proces aż pvm_barrier zostanie wywołane przez count człoków grupy. (każde wywołanie z tym samym parametrem count) (typowo: count = docelowy rozmiar grupy) PVM p. 42

pvm_reduce int info = pvm_reduce( void (*func)(), void *data, int count, int datatype, int msgtag, char *group, int rootginst) func - funkcja w C void func(int *datatype, void *x, void *y, int *num, int *info) x, num - odpowiadają dat i num w pvm_reduce y - otrzymane wartości (też rozmiaru num). predefiniowane: PvmMin, PvmMax, PvmSum, PvmProduct PVM p. 43

pvm_reduce data - wskaźnik do początku tablicy lokalnych wartości. w korzeniu w data zapisywany jest wynik. count - liczba elementów datatype w data. (jednakowy) datatype - typ danych: PVM_BYTE, PVM_SHORT, PVM_INT...... rootginst - instance number członka grupy, który otrzyma wynik Redukcja wykonywana element-wise na data. Wada: jest nieblokująca. Może wymagać pvm_barrier. PVM p. 44

mmult.c /* Matrix Multiply */ /* defines and prototypes for the PVM library */ #include <pvm3.h> #include <stdio.h> /* Maximum number of children this program will spawn */ #define MAXNTIDS 100 #define MAXROW 10 /* Message tags */ #define ATAG 2 #define BTAG 3 #define DIMTAG 5 PVM p. 45

mmult.c void InitBlock(float *a, float *b, float *c, int blk, int row, int col) { int len, ind; int i,j; srand(pvm_mytid()); len = blk*blk; for (ind = 0; ind < len; ind++) { a[ind]=(float)(rand()%1000)/100.0; c[ind]=0.0; } for (i = 0; i < blk; i++) { for (j = 0; j < blk; j++) { if (row == col) b[j*blk+i]=(i==j)?1.0:0.0; else b[j*blk+i]=0.0; } } } PVM p. 46

mmult.c void BlockMult(float* c, float* a, float* b, int blk) { int i,j,k; } for (i = 0; i < blk; i++) for (j = 0; j < blk; j ++) for (k = 0; k < blk; k++) c[i*blk+j] += (a[i*blk+k] * b[k*blk+j]); PVM p. 47

mmult.c int main(int argc, char* argv[]){ /* number of tasks to spawn, use 3 as the default */ int ntask = 2; /* return code from pvm calls */ int info; /* my task and group id */ int mytid, mygid; /* children task id array */ int child[maxntids-1]; int i, m, blksize; /* array of the tids in my row */ int myrow[maxrow]; float *a, *b, *c, *atmp; int row, col, up, down; PVM p. 48

mmult.c /* find out my task id number */ mytid = pvm_mytid(); // pvm_advise(pvmroutedirect); /* check for error */ if (mytid < 0) { /* print out the error */ pvm_perror(argv[0]); /* exit the program */ return -1; } /* join the mmult group */ mygid = pvm_joingroup("mmult"); if (mygid < 0) { pvm_perror(argv[0]); pvm_exit(); return -1; } PVM p. 49

mmult.c /* if my group id is 0 then I must spawn the other tasks */ if (mygid == 0) { /* find out how many tasks to spawn */ if (argc == 3) { m = atoi(argv[1]); blksize = atoi(argv[2]); } if (argc < 3) { fprintf(stderr, "usage: mmult m blk\n"); pvm_lvgroup("mmult"); pvm_exit(); return -1; } PVM p. 50

mmult.c /* make sure ntask is legal */ ntask = m*m; if ((ntask < 1) (ntask >= MAXNTIDS)) { fprintf(stderr, "ntask = %d not valid.\n", ntask); pvm_lvgroup("mmult"); pvm_exit(); return -1; } /* no need to spawn if there is only one task */ if (ntask == 1) goto barrier; /* spawn the child tasks */ info = pvm_spawn("mmult", (char**)0, PvmTaskDefault, (char*)0, ntask-1, child); PVM p. 51

mmult.c /* make sure spawn succeeded */ if (info!= ntask-1) { pvm_lvgroup("mmult"); pvm_exit(); return -1; } /* send the matrix dimension */ pvm_initsend(pvmdatadefault); pvm_pkint(&m, 1, 1); pvm_pkint(&blksize, 1, 1); pvm_mcast(child, ntask-1, DIMTAG); } PVM p. 52

mmult.c else { /* recv the matrix dimension */ pvm_recv(pvm_gettid("mmult", 0), DIMTAG); pvm_upkint(&m, 1, 1); pvm_upkint(&blksize, 1, 1); ntask = m*m; } PVM p. 53

mmult.c /* make sure all tasks have joined the group */ barrier: info = pvm_barrier("mmult",ntask); if (info < 0) pvm_perror(argv[0]); /* find the tids in my row */ for (i = 0; i < m; i++) myrow[i] = pvm_gettid("mmult", (mygid/m)*m + i); /* allocate the memory for the local blocks */ a = (float*)malloc(sizeof(float)*blksize*blksize); b = (float*)malloc(sizeof(float)*blksize*blksize); c = (float*)malloc(sizeof(float)*blksize*blksize); atmp = (float*)malloc(sizeof(float)*blksize*blksize); PVM p. 54

mmult.c /* check for valid pointers */ if (!(a && b && c && atmp)) { fprintf(stderr, "%s: out of memory!\n", argv[0]); free(a); free(b); free(c); free(atmp); pvm_lvgroup("mmult"); pvm_exit(); return -1; } /* find my block s row and column */ row = mygid/m; col = mygid % m; /* calculate the neighbor s above and below */ up = pvm_gettid("mmult", ((row)?(row-1):(m-1))*m+col); down = pvm_gettid("mmult", ((row == (m-1))?col:(row+1)*m+col)); /* initialize the blocks */ InitBlock(a, b, c, blksize, row, col); PVM p. 55

mmult.c /* do the matrix multiply */ for (i = 0; i < m; i++) { /* mcast the block of matrix A */ if (col == (row + i)%m) { pvm_initsend(pvmdatadefault); pvm_pkfloat(a, blksize*blksize, 1); pvm_mcast(myrow, m, (i+1)*atag); BlockMult(c,a,b,blksize); } else { pvm_recv(pvm_gettid("mmult", row*m + (row +i)%m), (i+1)*atag); pvm_upkfloat(atmp, blksize*blksize, 1); BlockMult(c,atmp,b,blksize); } PVM p. 56

mmult.c /* rotate the columns of B */ pvm_initsend(pvmdatadefault); pvm_pkfloat(b, blksize*blksize, 1); pvm_send(up, (i+1)*btag); pvm_recv(down, (i+1)*btag); pvm_upkfloat(b, blksize*blksize, 1); } PVM p. 57

mmult.c /* check it */ for (i = 0 ; i < blksize*blksize; i++) if (a[i]!= c[i]) printf("error a[%d] (%g)!= c[%d] (%g) \n", i, a[i],i,c[i]); } printf("done.\n"); free(a); free(b); free(c); free(atmp); pvm_lvgroup("mmult"); pvm_exit(); return 0; PVM p. 58