Skip to main content

This is my blog, more about me at marianoguerra.github.io

πŸ¦‹ @marianoguerra.org 🐘 @marianoguerra@hachyderm.io 🐦 @warianoguerra

Resolviendo ejercicios de MPI (y tambien en erlang) Parte 2

enunciado del ejercicio 2

Write a program that reads an integer value from the terminal and distributes the value to all of the MPI processes. Each process should print out its rank and the value it received. Values should be read until a negative integer is given as input.

lo resolvi ahi nomas con MPI, lo corri y todo andaba bien excepto que los procesos no imprimian (excepto el rank 0), pelee, toque, agregue fflush(stdout) y printf's por todos lados (clasica estrategia de debugger artesanal de C :D) y nada, copie el ejercicio resuelto de la pagina y le pasa lo mismo, asi que asumo que es algo relacionado con que mi notebook no es un cluster y encima tiene un solo core. aunque no sirva de mucho, aca esta la resolucion en C:

#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 */
printf("process %d of %d\n", rank, size);

do {
if(rank == 0) {
printf("give me a value: ");
scanf("%d", &value);
MPI_Bcast(&value, 1, MPI_INT, 0, MPI_COMM_WORLD);
}
else {
MPI_Recv(&value, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
printf("process %d received %d\n", rank, value);
fflush(stdout);
}
} while(value >= 0);
printf("negative value, closing\n");

MPI_Finalize();
return 0;
}


el programa compila y corre, por el hecho de que me pida los valores sucesivos asumo que los procesos estan recibiendo los valores (si no se colgaria en el broadcast) pero de todas formas no imprime.

bueno, pase a la resolucion en erlang, aca esta el codigo:

-module(ej2).
-export([run/1]).

run(Total) ->
Pids = spawn_listeners(Total),
get_values(Pids).

spawn_listeners(Count) -> spawn_listeners(Count, []).

spawn_listeners(0, Pids) -> Pids;
spawn_listeners(Count, Pids) ->
Pid = spawn(fun() -> listener() end),
spawn_listeners(Count - 1, [Pid|Pids]).

listener() ->
receive
Number ->
io:format("process ~p received ~p~n", [self(), Number]),
if
Number >= 0 -> listener();
true ->
io:format("negative value, closing ~p~n", [self()])
end
end.

get_values(Pids) ->
case io:get_line("give me a value (negative to quit): ") of
{error, Reason} ->
io:format("error reading value (~p)~n", [Reason]);
eof ->
io:format("error reading value~n");
Value ->
case string:to_integer(Value) of
{error, Reason} ->
io:format("invalid value (~p)~n", [Reason]),
get_values(Pids);
{IntValue, _Rest} ->
send_values(IntValue, Pids),
if
IntValue >= 0 -> get_values(Pids);
true -> io:format("negative value, closing~n")
end
end
end.

send_values(Value, Pids) ->
lists:foreach(fun(Pid) -> Pid ! Value end, Pids).



algunas observaciones, en este programa se pueden crear multiples grupos que escuchen a multiples entradas y de tamaΓ±os variables sin cambiar el codigo.
Una observacion sobre erlang es lo raro que es la convencion de los delimitadores, por ejemplo:

  • Si es la ultima sentencia de una funcion va con punto (a excepcion de que este haciendo pattern matching en cuyo caso todos menos la ultima son con punto y coma)
  • Si es una sentencia comun dentro de una funcion termina en coma, a excepcion de que sea la ultima de la funcion (en cuyo caso punto o punto y coma como vimos arriba) pero tambien a excepcion de que sea la ultima de un if, case, receive en cuyo caso es ;, pero no si es la ultima del ultimo statement en cuyo caso no lleva nada.
estas son algunas nomas, no me costo mucho entenderlas pero lleva un tiempo acostumbrarse y por ahi le erras, mas si moves codigo o agregas statements en cuyo caso tenes que revisar los terminadores.

ejemplo de la salida del de erlang (probando enteros positivos, negativos y valores invalidos):



$ erl
Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [kernel-poll:false]

Eshell V5.6.5 (abort with ^G)
1> c(ej2).
{ok,ej2}
2> ej2:run(4).
give me a value (negative to quit): 42
process received 42
process received 42
process received 42
process received 42
give me a value (negative to quit): 7
process received 7
process received 7
process received 7
process received 7
give me a value (negative to quit): -1
negative value, closing
process received -1
process received -1
process received -1
process received -1
negative value, closing
negative value, closing
negative value, closing
negative value, closing
ok
3> ej2:run(4).
give me a value (negative to quit): asd
invalid value (no_integer)
give me a value (negative to quit): -1
negative value, closing
process received -1
process received -1
process received -1
process received -1
negative value, closing
negative value, closing
negative value, closing
negative value, closing
ok
4>