Appendice B
File “EsempioAssistantV2.ast”:
/************************************************************************ Esempio di applicazione parallela per la validazione del modello
ASSISTANT
Versione iniziale dell'applicazione di esempio con implementazioni task parallel (FARM) e data parallel (MAP) dei moduli Elabora e Presenta e realizzazione sequenziale dei moduli Genera.
Tesi di Gabriele Mencagli <mencagli@di.unipi.it>
************************************************************************/ //Versione del programma con Switching delle implementazioni parallele //realizzate con singoli PARMOD:
//Dimensione dei vettori di input e delle righe della matrice di output //dell'applicazione:
#define N 5000
//Lunghezza degli stream prodotti dai moduli Genera_*: #define STREAMLENGTH 500
//I tempi di attesa sono espressi in microsecondi:
//Intervallo tra la generazione di due item di Genera_1: #define WAITGEN1 80000
//Intervallo tra la generazione di due item di Genera_2: #define WAITGEN2 70000
//Intervallo tra la generazione di due item di Genera_3: #define WAITGEN3 60000
//I tempi di attesa sono espressi in secondi:
//Tempo di attesa per la funzione F eseguita da Elabora: #define WAITFFUNCTION 5
//Tempo di attesa per il calcolo della matrice eseguito da Presenta: #define WAITMATRIXCOMPUTATION 120
//I tempi di attesa sono espressi in microsecondi:
//Tempo di attesa per il calcolo di una riga della matrice eseguito da //Presenta:
#define WAITROWMATRIXCOMPUTATION 24000 //Define utili:
#define TASK_PARALLEL 0 #define DATA_PARALLEL 1
//Main dell'applicazione di esempio per la validazione di ASSISTANT: generic main() {
stream long[N] input1Elabora; stream long[N] input2Elabora; stream long[N] input1ElaboraFarm; stream long[N] input2ElaboraFarm; stream long[N] input1ElaboraMap; stream long[N] input2ElaboraMap;
stream long[N] outputElabora; stream long[N] input2Presenta;
stream long[N] outputElaboraPerFarm; stream long[N] input2PresentaFarm; stream long[N] outputElaboraPerMap; stream long[N] input2PresentaMap; stream long[N][N] outputPresenta; stream long switchingControl1; stream long switchingControl2;
Genera1(output_stream input1Elabora); Genera2(output_stream input2Elabora); Genera3(output_stream input2Presenta);
EnvControl1(output_stream switchingControl1); EnvControl2(output_stream switchingControl2);
Switching1(input_stream input1Elabora, input2Elabora, switchingControl1 output_stream input1ElaboraFarm,
input2ElaboraFarm, input1ElaboraMap, input2ElaboraMap); Elabora(input_stream input1ElaboraFarm, input2ElaboraFarm,
input1ElaboraMap, input2ElaboraMap output_stream outputElabora);
Switching2(input_stream outputElabora, input2Presenta, switchingControl2 output_stream outputElaboraPerFarm,
input2PresentaFarm, outputElaboraPerMap, input2PresentaMap);
Presenta(input_stream outputElaboraPerFarm, input2PresentaFarm, outputElaboraPerMap, input2PresentaMap output_stream
outputPresenta);
Stampa(input_stream outputPresenta); }
//Definizione del modulo sequenziale Genera1. Nel documento è indicato //che e' un PARMOD per adesso lo consideriamo un sequenziale:
Genera1(output_stream long input1Elabora[N]) {
generaArray1(output_stream input1Elabora); }
//Definizione del modulo sequenziale Genera2. Nel documento è indicato //che e' un PARMOD per adesso lo consideriamo un sequenziale:
Genera2(output_stream long input2Elabora[N]) {
generaArray2(output_stream input2Elabora); }
//Definizione del modulo sequenziale Genera3. Nel documento è indicato //che e' un PARMOD per adesso lo consideriamo sequenziale:
Genera3(output_stream long input2Presenta[N]) {
generaArray3(output_stream input2Presenta); }
//Proc che genera uno stream di lunghezza STREAMLENGTH di vettori di N //long random:
proc generaArray1(output_stream long v[N]) inc<"stdlib.h", "unistd.h", "time.h">
$c++{
//Definisco il seed utilizzato per la generazione dei numeri //pseudocasuali dei vettori di input:
time_t tempo;
tempo = time(&tempo); srand(((int) tempo) + 1); long vettore[N];
for(int count = 0; count < STREAMLENGTH; count++){
for(int i = 0; i < N; i++) vettore[i] = 1 + (long) (100.0*rand()/(RAND_MAX + 1.0));
//Attendo per un certo tempo in modo da simulare una //specifico tempo di interpartenza:
usleep(WAITGEN1);
assist_out(v, vettore); }
}c++$
//Proc che genera uno stream di lunghezza STREAMLENGTH di vettori di N //long random:
proc generaArray2(output_stream long v[N]) inc<"stdlib.h", "unistd.h", "time.h"> $c++{
//Definisco il seed utilizzato per la generazione dei numeri //pseudocasuali dei vettori di input:
time_t tempo;
tempo = time(&tempo); srand(((int) tempo) + 2); long vettore[N];
for(int count = 0; count < STREAMLENGTH; count++){
for(int i = 0; i < N; i++) vettore[i] = 1 + (long) (100.0*rand()/(RAND_MAX + 1.0));
//Attendo per un certo tempo in modo da simulare una //specifico tempo di interpartenza:
usleep(WAITGEN2);
assist_out(v, vettore); }
}c++$
//Proc che genera uno stream di lunghezza STREAMLENGTH di vettori di N //long random:
proc generaArray3(output_stream long v[N]) inc<"stdlib.h", "unistd.h", "time.h"> $c++{
//Definisco il seed utilizzato per la generazione dei numeri //pseudocasuali dei vettori di input:
time_t tempo;
tempo = time(&tempo); srand(((int) tempo) + 3); long vettore[N];
for(int count = 0; count < STREAMLENGTH; count++){
for(int i = 0; i < N; i++) vettore[i] = 1 + (long) (100.0*rand()/(RAND_MAX + 1.0));
//Attendo per un certo tempo in modo da simulare una //specifico tempo di interpartenza:
usleep(WAITGEN3);
assist_out(v, vettore); }
}c++$
//Definizione del modulo sequenziale che produce gli eventi esterni per //il primo switching:
EnvControl1(output_stream long switchingControl1){ env_switch(output_stream switchingControl1); }
//Definizione del modulo sequenziale che produce gli eventi esterni per //il secondo switching:
EnvControl2(output_stream long switchingControl2){ env_switch(output_stream switchingControl2); }
//Proc che genera gli eventi esterni: proc env_switch(output_stream long event) inc<"fstream","iostream">
$c++{
int choice;
bool scelta = false; bool finito = false; while(!finito){
while(!scelta){
cout << "Scegli lo switching da eseguire:" << endl; cout << "0 - TASK PARALLEL" << endl;
cout << "1 - DATA PARALLEL" << endl; cout << "2 - ESCI" << endl;
cin >> choice;
if((choice == 0)||(choice == 1)||(choice == 2)) scelta = true;
}
if(choice == 2) finito = true; else assist_out(event, choice); scelta = false;
} }c++$
//Modulo sequenziale che effettua la stampa su file delle matrici //calcolate da Presenta:
Stampa(input_stream long outputPresenta[N][N]) inc<"fstream","iostream">
$c++{
static int count = 1;
cout << "Il modulo Stampa ha ricevuto la matrice " << count << "/" << STREAMLENGTH << "" << std::endl; ;
std::ofstream f;
f.open ("FileMatrici.txt", fstream::out|fstream::app);
f << "Scrittura della matrice numero " << count << std::endl; for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++) f << outputPresenta[i][j] << " "; f << std::endl;
}
f << std::endl;
//Aggiorno l'indice delle matrici ricevute: count++;
//Controllo la fine dello stream: if (count > STREAMLENGTH){
//Fine della stampa su file:
f << "Fine della stampa delle matrici ricevute" << std::endl; }
f.close(); }c++$
//Proc per aggiornare l'attributo sulla modalita' di switching: proc init_attrib (out long a)
$c++{
a = TASK_PARALLEL; }c++$
//PARMOD ONE che esegue lo switching del modulo Elabora: parmod Switching1(input_stream long input1Elabora[N], long
input2Elabora[N], long switchingControl1 output_stream long input1ElaboraFarm[N], long input2ElaboraFarm[N], long input1ElaboraMap[N], long input2ElaboraMap[N]){ topology one pv;
attribute long behaviour onto pv; init {
//La modalita' di default e' TASK_PARALLEL: VP {
init_attrib (out behaviour); }
}
do input_section {
guard0: on ,, input1Elabora&&input2Elabora { distribution input1Elabora broadcast to pv;
distribution input2Elabora broadcast to pv; }
guard1: on ,, switchingControl1 {
distribution switchingControl1 broadcast to pv; }
} while(true)
virtual_processors {
elab0 (in guard0 out input1ElaboraFarm, input2ElaboraFarm, input1ElaboraMap, input2ElaboraMap) {
VP {
procSwitch(in input1Elabora, input2Elabora, behaviour output_stream input1ElaboraFarm,
input2ElaboraFarm, input1ElaboraMap, input2ElaboraMap);
}
}
elab1 (in guard1) { VP {
update_TaskMode(in switchingControl1 out behaviour);
}
} }
output_section {
collects input1ElaboraFarm from ANY pv; collects input2ElaboraFarm from ANY pv; collects input1ElaboraMap from ANY pv; collects input2ElaboraMap from ANY pv; }
}
//Definizione della proc procSwitch eseguita dal PARMOD di Switching: proc procSwitch(in long A[N], long B[N], long mode output_stream long A1[N], long B1[N], long A2[N], long B2[N])
path<"/home/p4/mencagli/proveAssistant"> $c++{
//Effettuo lo switching in base alla modalita' attuale: if(mode == TASK_PARALLEL){ assist_out(A1, A); assist_out(B1, B); } if(mode == DATA_PARALLEL){ assist_out(A2, A); assist_out(B2, B); } }c++$
//Definizione della proc update_TaskMode eseguita dal PARMOD di Switching //per modificare la modalita' di elaborazione:
proc update_TaskMode(in long mode out long bev) path<"/home/p4/mencagli/proveAssistant">
$c++{
if(mode == TASK_PARALLEL) cout << "ATTENZIONE MODIFICATA LA
MODALITA' DI ELABORAZIONE PASSAGGIO A TASK PARALLEL" << endl; else cout << "ATTENZIONE MODIFICATA LA MODALITA' DI ELABORAZIONE
PASSAGGIO A DATA PARALLEL" << endl;
cout <<"--- ---" << endl;
//Modifico il comportamento attuale: bev = mode;
}c++$
//Definizione del PARMOD Elabora:
parmod Elabora(input_stream long input1ElaboraFarm[N], long input2ElaboraFarm[N], long input1ElaboraMap[N], long
input2ElaboraMap[N] output_stream long outputElabora[N]) { topology array [i:N] pv;
attribute long S1[N] scatter S1[*i0] onto pv[i0]; stream long ris;
do input_section {
guard0: on ,, input1ElaboraFarm&&input2ElaboraFarm { distribution input1ElaboraFarm on_demand to pv;
distribution input2ElaboraFarm on_demand to pv; }
guard1: on ,, input1ElaboraMap&&input2ElaboraMap {
distribution input1ElaboraMap[*i1] scatter to S1[i1]; distribution input2ElaboraMap broadcast to pv;
}
} while(true)
virtual_processors {
elab0 (in guard0 out outputElabora) { VP i = 0..N-1 {
IteraF(in input1ElaboraFarm, input2ElaboraFarm out outputElabora);
}
}
elab1 (in guard1 out outputElabora) { VP i = 0..N-1 {
EseguiF(in S1[i], input2ElaboraMap out ris);
}
} }
output_section {
collects outputElabora from ANY pv; collects ris from ALL pv[i]{
long el; long local_result[N]; AST_FOR_EACH(el){ local_result[i] = el; } assist_out(outputElabora, local_result); }<>; } }
//Definizione della proc IteraF eseguita dai VP di Elabora versione FARM; proc IteraF(in long A[N], long B[N] out long C[N])
path<"/home/p4/mencagli/proveAssistant"> inc<"iostream","Function.h">
obj<"Function.o"> $c++{
//Attendo per un certo tempo in modo da simulare una specifico //tempo di interpartenza:
sleep(WAITFFUNCTION);
for(long i = 0; i < N; i++) C[i] = FunctionF(A[i], B);
cout << "Un worker di Elabora versione FARM ha prodotto un vettore C" << endl;
//Definizione della proc EseguiF eseguita dai VP di Elabora versione MAP; proc EseguiF(in long a, long b[N] out long c)
path<"/home/p4/mencagli/proveAssistant"> inc<"iostream","Function.h">
obj<"Function.o"> $c++{
//Attendo per un certo tempo in modo da simulare una specifico //tempo di interpartenza:
usleep((WAITFFUNCTION * 1000000) / STREAMLENGTH); c = FunctionF(a, b);
cout << "Un worker di Elabora versione MAP ha prodotto un elemento della vettore C" <<endl;
}c++$
//PARMOD one che esegue lo switching del modulo Presenta: parmod Switching2(input_stream long outputElabora[N], long
input2Presenta[N], long switchingControl2 output_stream long outputElaboraPerFarm[N], long input2PresentaFarm[N], long
outputElaboraPerMap[N], long input2PresentaMap[N]){ topology one pv;
attribute long behaviour onto pv; init {
//La modalita' di default e' TASK_PARALLEL: VP {
init_attrib (out behaviour); }
}
do input_section {
guard0: on ,, outputElabora&&input2Presenta { distribution outputElabora broadcast to pv;
distribution input2Presenta broadcast to pv; }
guard1: on ,, switchingControl2 {
distribution switchingControl2 broadcast to pv; }
} while(true)
virtual_processors {
elab0 (in guard0 out outputElaboraPerFarm, input2PresentaFarm, outputElaboraPerMap,
input2PresentaMap) { VP {
procSwitch2(in outputElabora, input2Presenta, behaviour output_stream outputElaboraPerFarm, input2PresentaFarm, outputElaboraPerMap, input2PresentaMap); } }
elab1 (in guard1) { VP {
update_TaskMode(in switchingControl2 out behaviour);
}
} }
output_section {
collects outputElaboraPerFarm from ANY pv; collects input2PresentaFarm from ANY pv; collects outputElaboraPerMap from ANY pv; collects input2PresentaMap from ANY pv; }
//Definizione della proc procSwitch eseguita dal PARMOD di Switching 2: proc procSwitch2(in long C[N], long D[N], long mode output_stream long
C1[N], long D1[N], long C2[N], long D2[N]) path<"/home/p4/mencagli/proveAssistant">
$c++{
//Effettuo lo switching in base alla modalita' attuale: if(mode == TASK_PARALLEL){ assist_out(C1, C); assist_out(D1, D); } if(mode == DATA_PARALLEL){ assist_out(C2, C); assist_out(D2, D); } }c++$
//Definizione del PARMOD Presenta:
parmod Presenta(input_stream long outputElaboraPerFarm[N], long input2PresentaFarm[N], long outputElaboraPerMap[N], long
input2PresentaMap[N] output_stream long outputPresenta [N][N]){
topology array [i:N] pv;
attribute long S2[N] scatter S2[*i0] onto pv[i0]; stream long ris[N];
do input_section {
guard0: on ,, outputElaboraPerFarm&&input2PresentaFarm { distribution outputElaboraPerFarm on_demand to pv;
distribution input2PresentaFarm on_demand to pv; }
guard1: on ,, outputElaboraPerMap&&input2PresentaMap { distribution outputElaboraPerMap[*i1] scatter to
S2[i1];
distribution input2PresentaMap broadcast to pv; }
} while(true)
virtual_processors {
elab0 (in guard0 out outputPresenta) { VP i = 0..N-1 {
CalcoloMatrice(in outputElaboraPerFarm, input2PresentaFarm out outputPresenta);
}
}
elab1 (in guard1 out outputPresenta) { VP i = 0..N-1 {
ProdottoRowMatrix(in S2[i], input2PresentaMap out ris);
}
} }
output_section {
collects outputPresenta from ANY pv; collects ris from ALL pv[i] {
static long result[N][N]; const long *el;
AST_FOR_EACH(el) { for(int j = 0;j < N;j++) result[i][j]=el[j]; } assist_out(outputPresenta,result); }<>; } }
//versione FARM;
proc CalcoloMatrice(in long C[N], long D[N] out long E[N][N]) path<"/home/p4/mencagli/proveAssistant">
inc<"iostream","Function.h"> obj<"Function.o">
$c++{
//Attendo per un certo tempo in modo da simulare una specifico //tempo di interpartenza: sleep(WAITMATRIXCOMPUTATION); for(int i = 0; i < N; i++){ for(int j = 0; j < N; j++){ E[i][j] = FunctionG(C[i], D[j]); } }
cout << "Un worker di Presenta versione FARM ha prodotto una matrice E" << endl;
}c++$
//Definizione della proc ProdottoRowMatrix eseguita dai VP di Presenta //versione MAP:
proc ProdottoRowMatrix(in long c, long d[N] out long e[N]) path<"/home/p4/mencagli/proveAssistant">
inc<"iostream","Function.h"> obj<"Function.o">
$c++{
for(int i = 0; i < N; i++){ e[i] = FunctionG(c, d[i]); }
//Attendo per un certo tempo in modo da simulare una specifico //tempo di interpartenza:
usleep(WAITROWMATRIXCOMPUTATION);
cout << "Un worker di Presenta versione MAP ha prodotto una riga della matrice E" << endl;