Resolviendo ejercicios de MPI (y tambien en erlang) Parte 4
Sigo molestando con estos problemas, me salte uno que no me daba ganas de resolver y pase al siguiente:
http://www.mcs.anl.gov/research/projects/mpi/tutorial/mpiexmpl/src/ring/C/main.html
Write a program that takes data from process zero and sends it to all of the other processes by sending it in a ring. That is, process i should receive the data and send it to process i+1, until the last process is reached.
la solucion en C salio bastante facil haciendo copypasta de los problemas anteriores y sorprendentemente en este caso los otros procesos si imprimieron a la consola:
#include <stdio.h>
#include <mpi.h>
int main (int argc, char** argv) {
int rank, size, value, i;
MPI_Status status;
MPI_Init (&argc, &argv); /* starts MPI */
MPI_Comm_rank (MPI_COMM_WORLD, &rank); /* get current process id */
MPI_Comm_size (MPI_COMM_WORLD, &size); /* get number of processes */
do {
if(rank == 0) {
printf("give me a value: ");
scanf("%d", &value);
fflush(stdout);
MPI_Send(&value, 1, MPI_INT, rank + 1, 1, MPI_COMM_WORLD);
}
else{
MPI_Recv(&value, 1, MPI_INT, rank - 1, 1, MPI_COMM_WORLD, &status);
printf("process %d received %d\n", rank, value);
if(rank + 1 < size) {
printf("sending to %d\n", rank + 1, value);
MPI_Send(&value, 1, MPI_INT, rank + 1, 1, MPI_COMM_WORLD);
}
fflush(stdout);
}
} while(value >= 0);
printf("negative value, closing\n");
MPI_Finalize();
return 0;
}
la solucion en erlang (tambien robando del ejercicio anterior):
-module(ej5).
-export([run/1]).
run(Total) ->
NextPid = spawn_listeners(Total),
get_values(NextPid).
spawn_listeners(Count) -> spawn_listeners(Count, none).
spawn_listeners(0, NextPid) -> NextPid;
spawn_listeners(Count, LastPid) ->
NextPid = spawn(fun() -> listener(LastPid) end),
spawn_listeners(Count - 1, NextPid).
listener(NextPid) ->
receive
Int ->
io:format("process ~p received ~p~n", [self(), Int]),
if
NextPid /= none ->
io:format("sending to ~p~n", [NextPid]),
NextPid ! Int;
true -> ok
end,
if
Int >= 0 -> listener(NextPid);
true ->
io:format("negative value, closing ~p~n", [self()])
end
end.
get_value(Message, ConversionFun) ->
case io:get_line(Message) of
{error, Reason} -> {error, Reason};
eof -> {error, eof};
Value -> ConversionFun(Value)
end.
get_values(NextPid) ->
case get_value("give me an int value (negative to quit): ", fun(Val) -> string:to_integer(Val) end) of
{error, Reason} ->
io:format("error reading int value (~p)~n", [Reason]),
get_values(NextPid);
{IntValue, _Rest} ->
io:format("sending to ~p~n", [NextPid]),
NextPid ! IntValue,
if
IntValue >= 0 -> get_values(NextPid);
true -> io:format("negative value, closing~n")
end
end.
ejemplo de salida:
$ erl
Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [kernel-poll:false]
Eshell V5.6.5 (abort with ^G)
1> c(ej5).
{ok,ej5}
2> ej5:run(3).
give me an int value (negative to quit): 3
sending to
process received 3
sending to
process received 3
sending to
process received 3
give me an int value (negative to quit): asd
error reading int value (no_integer)
give me an int value (negative to quit): 42
sending to
process received 42
sending to
process received 42
sending to
process received 42
give me an int value (negative to quit): -1
sending to
negative value, closing
process received -1
sending to
ok
negative value, closing
process received -1
sending to
negative value, closing
process received -1
negative value, closing