Skip to content

Instantly share code, notes, and snippets.

@mgarciaisaia
Last active August 29, 2015 14:20
Show Gist options
  • Save mgarciaisaia/5893b74b80ae07b24d69 to your computer and use it in GitHub Desktop.
Save mgarciaisaia/5893b74b80ae07b24d69 to your computer and use it in GitHub Desktop.
Explicación sobre redirección de stdin y stdout en ReduceMapFast

Si nos hubieran dado una piña por cada pregunta o duda sobre la redirección del STDIN y STDOUT, ya estaríamos vendiendo ananás en alguna playa de Brasil.

El objetivo del sistema a construir en ReduceMapFast es ejecutar tareas de análisis de grandes volúmenes de datos aprovechando el nivel de paralelismo que ofrece un cluster de computadoras organizadas correctamente.

Para ello, los Nodos deberán ejecutar una determinada rutina de map sobre los diversos bloques de datos que conformen un archivo, y los almacenarán en archivos temporales para luego aplicar el reduce.

Podríamos pensar que el Nodo ejecuta algo equivalente a esta instrucción en Bash:

cat bloque-de-datos | ./map > /tmp/archivo-temporal

Aplicando mejor la redirección, podemos obviar a cat:

./map < bloque-de-datos > /tmp/archivo-temporal

Pero el bloque de datos no está aislado: es parte de un gran archivo que representa todo nuestro espacio de datos. Para el bloque número N del Nodo (0-based, obviamente), de longitud L (en bytes), podemos leer los L bytes que están a partir del byte N*20*1024. Pongamos como ejemplo el bloque 3, con sus 20 MB completos:

tail -c 62914560 < espacio-almacenamiento.bin | head -c 20971520 > /tmp/archivo-temporal

Es decir, leer el archivo espacio-almacenamiento.bin a partir de los primeros 60 MB, y quedarse con los primeros 20 MB de eso, mandándolos al archivo /tmp/archivo-temporal.

Si armáramos una función en nuestro código que, a partir de N y L generara un string como el que tenemos que ejecutar, y ese string se lo enviáramos a la función system(), ella se encargaría de ejecutar eso en una shell y conseguir el resultado que necesitamos.

Pero siempre hay peros; si no, no te estaría escribiendo la solución :)

El primero pero es que eso es horriblemente lento y derrochador de I/O. Yo no lo probé, no voy a mentirte (o, al menos, por ahora), pero en Internet dicen que es así1. Tiene sentido: el tail va a leer TODO el resto del espacio de almacenamiento, para que luego head lo corte.

El segundo pero es que analizar grandes volúmenes de datos es el objetivo del sistema a construir en ReduceMapFast, pero el objetivo de ReduceMapFast es ayudar a quienes cursan Sistemas Operativos a fijar y ahondar en los conceptos de la materia. Delegar toda esa redirección a la shell del sistema ayuda a que Chet Ramey entienda mejor Sisop, que asumo que ya sabrá bastante.

Cuando redirigimos la entrada, salida o error estándar de un proceso desde Bash, lo que hacemos simplemente es modificar a qué archivo referencia el file descriptor correspondiente (0, 1 o 2, respectivamente). Para el TP hay que hacer eso, pero el problema es que no tenemos un archivo que especificarle como entrada al map, porque el bloque de datos es sólo una parte de todo el archivo del espacio de almacenamiento. Si estás considerando leer 20 MB del espacio de almacenamiento, guardarlos en un nuevo archivo y especificar ese nuevo archivo para la redirección... volvé a leerte todo el post desde el principio :)

Lo que sí estaría muy bien hacer es enviar esos 20 MB de datos a algo que tenga una interfaz similar a la de un archvio (meh, con tener un file descriptor numérico que podamos usar para hacer la redirección nos alcanza), pero que no se persista en ningún lado, para no abusar de la I/O, y luego ejecutar el ./map diciendole que ese algo sea su STDIN2.

Ese algo se llama pipe, uno de los mecanismos de IPC que nos provee Linux. La idea es que te genera un file descriptor por el que podés leer lo que se escriba en el otro file descriptor que te genera.

Si te contara cómo usarlo, sería un buen indicador de que no te soluciona los problemas del TP. Buenas noticias: hasta acá llegó el post.

¡Happy piping!

Footnotes

  1. Y, ya lo dijo Einstein: todo lo que está en Internet es cierto.

  2. El STDOUT podemos mandarlo a un archivo temporal sin problemas, porque va completo, pero seguramente quieras igual especificar esa redirección desde C para aprovechar alguna función como mkstemp para darle un nombre único.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment