%% demo1_mpe.pl %% %% This file was originally created on 3/7/2003 %% by Stasinos Konstantopoulos %% as part of the YAP Prolog distribution. %% %% This file is in the Public Domain. %% demo1_mpe.pl is the same as demo1.pl, except %% that MPE is used to log MPI activity. % make the `floor' operator return integer values :- set_prolog_flag(language, iso). %% %% This the calculation that needs to be performed, in this case %% the sum of [From..To] %% calc(From, From, Acc, Res) :- !, Res is Acc + From. calc(From, To, Acc, Res) :- !, Acc1 is Acc + To, To1 is To - 1, calc(From, To1, Acc1, Res). %% %% The master node sends teh task definition to %% the workers and then collects the results %% do(0, NumProc):- !, % processing state mpe_create_event(Ev1), mpe_create_event(Ev2), mpe_create_state(Ev1,Ev2,processing,green), % bcasting state mpe_create_event(Ev3), mpe_create_event(Ev4), mpe_create_state(Ev3,Ev4,bcasting,red), % sending/recving state mpe_create_event(Ev5), mpe_create_event(Ev6), mpe_create_state(Ev5,Ev6,'sending/receiving',brown), % pretend that the other nodes do not have % access to the task definition. % retrieve it and broadcast it. get_value(from, From), get_value(to, To), mpe_log(Ev3,0,event3), mpi_bcast(msg(From,To), 0), mpe_log(Ev4,0,event4), % loop to collect and accumulate partial results % from the workers set_value(n, NumProc), set_value(acc, 0), repeat, mpe_log(Ev5,0,event5), mpi_receive(T, Source, Tag), mpe_log(Ev6,0,event6), format( '0: Proc ~q said: ~q (Tag: ~q)~n', [Source,T,Tag] ), % accumulate results get_value(acc, Acc), NewAcc is Acc + T, set_value(acc, NewAcc), % processors still left get_value(n, Counter), NewCounter is Counter - 1, set_value(n, NewCounter), NewCounter == 1, !, format('0: Sum(~q..~q) = ~q.~n', [From,To,NewAcc]). %% %% The workers hear from the master what needs to %% be done, do the work and then send the results back. %% do(Rank, NumProc):- !, % processing state mpe_create_event(Ev1), mpe_create_event(Ev2), mpe_create_state(Ev1,Ev2,processing,green), % bcasting state mpe_create_event(Ev3), mpe_create_event(Ev4), mpe_create_state(Ev3,Ev4,bcasting,red), % sending/recving state mpe_create_event(Ev5), mpe_create_event(Ev6), mpe_create_state(Ev5,Ev6,'sending/receiving',brown), % catch the task broadcast mpe_log(Ev3,0,event3), mpi_bcast(Msg, 0), mpe_log(Ev4,0,event4), Msg = msg(From,To), format( '~q: All are calculating ~q..~q.~n', [Rank,From,To] ), MyFrom is floor(To * (Rank - 1) / (NumProc - 1)) + From, MyTo is floor(To * Rank / (NumProc - 1)) + From - 1, format( '~q: I am calculating ~q..~q.~n', [Rank,MyFrom,MyTo] ), % do the job mpe_log(Ev1,0,event1), calc( MyFrom, MyTo, 0, Result ), mpe_log(Ev2,0,event2), format( '~q: sending ~q to 0. (Tag: 1)~n', [Rank,Result] ), % send back the results mpe_log(Ev5,0,event5), mpi_send(Result, 0, 1), mpe_log(Ev6,0,event6). %% %% This is the entry point %% start(From, To):- % store the task definition set_value(from, From), set_value(to, To), mpi_open(Rank, NumProc, ProcName), format('Rank: ~q NumProc: ~q, ProcName: ~q~n', [Rank,NumProc,ProcName]), mpe_open, do(Rank, NumProc), format( 'Rank ~q finished!~n', [Rank] ), mpe_close( demo1_mpe ), mpi_close.