Está en la página 1de 60

Traducido del inglés al español - www.onlinedoctranslator.

com

20
Capitulo 2

MapReduce y la nueva pila


de software

Las aplicaciones modernas de minería de datos, a menudo llamadas análisis de “big data”, requieren
que administremos inmensas cantidades de datos rápidamente. En muchas de estas aplicaciones, los
datos son extremadamente regulares y existe una amplia oportunidad de explotar el paralelismo.
Algunos ejemplos importantes son:

1. La clasificación de las páginas web por importancia, que implica una multiplicación
repetida de matriz-vector donde la dimensión es de muchos miles de millones. Esta
aplicación, llamada “PageRank”, es el tema del Capítulo 5.

2. Búsquedas en redes de "amigos" en sitios de redes sociales, que involucran gráficos


con cientos de millones de nodos y muchos miles de millones de bordes. Las
operaciones en gráficos de este tipo se tratan en el Capítulo 10.

Para hacer frente a aplicaciones como estas, ha evolucionado una nueva pila de software.
Estos sistemas de programación están diseñados para obtener su paralelismo no de una
"supercomputadora", sino de "clústeres informáticos": grandes colecciones de hardware básico,
incluidos procesadores convencionales ("nodos informáticos") conectados por cables Ethernet o
conmutadores económicos. La pila de software comienza con una nueva forma de sistema de
archivos, llamado “sistema de archivos distribuido”, que presenta unidades mucho más grandes
que los bloques de disco en un sistema operativo convencional. Los sistemas de archivos
distribuidos también brindan replicación de datos o redundancia para proteger contra las fallas
frecuentes de los medios que ocurren cuando los datos se distribuyen en miles de nodos de
cómputo de bajo costo.
Además de estos sistemas de archivos, se han desarrollado muchos sistemas de
programación de alto nivel diferentes. El elemento central de la nueva pila de software es
un sistema de programación llamado Mapa reducido. Las implementaciones de
MapReduce permiten que muchos de los cálculos más comunes sobre datos a gran escala
se realicen en clústeres de computación de manera eficiente y tolerante a fallas de
hardware durante el cálculo.

21
22 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Los sistemas MapReduce están evolucionando y extendiéndose rápidamente. Hoy en


día, es común que los programas MapReduce se creen a partir de sistemas de
programación de un nivel aún más alto, a menudo una implementación de SQL. Además,
MapReduce resulta ser un caso útil, pero simple, de ideas más generales y poderosas.
Incluimos en este capítulo una discusión de generalizaciones de MapReduce, primero a
sistemas que soportan flujos de trabajo acíclicos y luego a sistemas que implementan
algoritmos recursivos.
Nuestro último tema de este capítulo es el diseño de buenos algoritmos MapReduce,
un tema que a menudo difiere significativamente del tema del diseño de buenos
algoritmos paralelos para ser ejecutados en una supercomputadora. Al diseñar algoritmos
de MapReduce, a menudo encontramos que el mayor costo está en la comunicación. Por
lo tanto, investigamos el costo de la comunicación y lo que nos dice sobre los algoritmos
MapReduce más eficientes. Para varias aplicaciones comunes de MapReduce, podemos
ofrecer familias de algoritmos que intercambian de manera óptima el costo de
comunicación con el grado de paralelismo.

2.1 Sistemas de archivos distribuidos

La mayor parte de la informática se realiza en un solo procesador, con su memoria principal,


caché y disco local (un nodo de cálculo). En el pasado, las aplicaciones que requerían
procesamiento paralelo, como grandes cálculos científicos, se realizaban en computadoras
paralelas de propósito especial con muchos procesadores y hardware especializado. Sin
embargo, la prevalencia de los servicios web a gran escala ha provocado que cada vez se haga
más informática en instalaciones con miles de nodos informáticos que operan de forma más o
menos independiente. En estas instalaciones, los nodos de cómputo son hardware básico, lo que
reduce en gran medida el costo en comparación con las máquinas paralelas de propósito
especial.
Estas nuevas instalaciones informáticas han dado lugar a una nueva generación de
sistemas de programación. Estos sistemas aprovechan el poder del paralelismo y al mismo
tiempo evitan los problemas de confiabilidad que surgen cuando el hardware informático
consta de miles de componentes independientes, cualquiera de los cuales podría fallar en
cualquier momento. En esta sección, discutimos tanto las características de estas
instalaciones informáticas como los sistemas de archivos especializados que se han
desarrollado para aprovecharlas.

2.1.1 Organización física de los nodos informáticos


La nueva arquitectura de computación paralela, a veces llamada computación en clúster,
está organizado de la siguiente manera. Los nodos de cómputo se almacenan en
bastidores quizás 8–64 en un estante. Los nodos en un solo rack están conectados por una
red, típicamente Gigabit Ethernet. Puede haber muchos racks de nodos informáticos y los
racks están conectados por otro nivel de red o un conmutador. El ancho de banda de la
comunicación entre racks es algo mayor que el de Ethernet intrarack, pero dada la
cantidad de pares de nodos que pueden necesitar comunicarse entre racks, esto
2.1. SISTEMAS DE ARCHIVOS DISTRIBUIDOS 23

el ancho de banda puede ser esencial. La figura 2.1 sugiere la arquitectura de un sistema
informático a gran escala. Sin embargo, puede haber muchos más racks y muchos más
nodos de cómputo por rack.

Cambiar

Racks de nodos informáticos

Figura 2.1: Los nodos de cómputo están organizados en racks y los racks están interconectados
por un conmutador

Es un hecho que los componentes fallan, y cuantos más componentes, como


nodos de cómputo y enlaces de comunicación, tenga un sistema, con más frecuencia
algo en el sistema no funcionará en un momento dado. Para sistemas como la figura
2.1, los principales modos de falla son la pérdida de un solo nodo (por ejemplo, el
disco en ese nodo se bloquea) y la pérdida de un bastidor completo (por ejemplo, la
red que conecta sus nodos entre sí y a la red). el mundo exterior falla).
Algunos cálculos importantes toman minutos o incluso horas en miles de nodos
de cómputo. Si tuviéramos que abortar y reiniciar el cálculo cada vez que fallara un
componente, es posible que el cálculo nunca se complete con éxito. La solución a
este problema tiene dos formas:

1. Los archivos deben almacenarse de forma redundante. Si no duplicamos el archivo en


varios nodos de cálculo, entonces, si un nodo falla, todos sus archivos no estarán
disponibles hasta que se reemplace el nodo. Si no hicimos una copia de seguridad de los
archivos y el disco falla, los archivos se perderían para siempre. Analizamos la gestión de
archivos en la Sección 2.1.2.

2. Los cálculos deben dividirse en tareas, de modo que si alguna de las tareas no se
ejecuta hasta su finalización, se pueda reiniciar sin afectar a otras tareas. Esta
estrategia es seguida por el sistema de programación MapReduce que presentamos
en la Sección 2.2.
24 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Implementaciones DFS

Hay varios sistemas de archivos distribuidos del tipo que hemos descrito.
ese se utilizan en la práctica. Entre estos:

1. los Sistema de archivos de Google ( GFS), el original de la clase.

2. Sistema de archivos distribuido Hadoop ( HDFS), un DFS de código abierto


utilizado con Hadoop, una implementación de MapReduce (consulte la
Sección 2.2) y distribuido por Apache Software Foundation.

3. Coloso es una versión mejorada de GFS, sobre la que se ha publicado poco. Sin
embargo, un objetivo de Colossus es proporcionar un servicio de archivos en
tiempo real.

2.1.2 Organización de sistemas de archivos a gran escala

Para explotar la computación en clúster, los archivos deben verse y comportarse de manera algo diferente a los
sistemas de archivos convencionales que se encuentran en computadoras individuales. Este nuevo sistema de
archivos, a menudo llamado sistema de archivos distribuido o DFS ( aunque este término ha tenido otros
significados en el pasado), se usa típicamente de la siguiente manera.

• Los archivos pueden ser enormes, posiblemente de un terabyte de tamaño. Si solo tiene
archivos pequeños, no tiene sentido usar un DFS para ellos.

• Los archivos rara vez se actualizan. Más bien, se leen como datos para algunos
cálculos y, de vez en cuando, se añaden datos adicionales a los archivos. Por
ejemplo, un sistema de reservas de aerolíneas no sería adecuado para un DFS,
incluso si los datos fueran muy grandes, porque los datos se cambian con mucha
frecuencia.

Los archivos se dividen en trozos que suelen tener un tamaño de 64 megabytes. Los
fragmentos se replican, quizás tres veces, en tres nodos informáticos diferentes. Además,
los nodos que contienen copias de un fragmento deben estar ubicados en diferentes
racks, para que no perdamos todas las copias debido a una falla en el rack. Por lo general,
un bastidor "falla" porque falla la interconexión entre los nodos de cómputo en el bastidor,
y el bastidor ya no puede comunicarse con nada fuera de sí mismo. Normalmente, el
usuario puede decidir tanto el tamaño del fragmento como el grado de replicación.
Para encontrar los fragmentos de un archivo, hay otro archivo pequeño llamado nodo maestro
o nodo de nombre para ese archivo. El nodo maestro se replica en sí mismo y un directorio para
el sistema de archivos en su conjunto sabe dónde encontrar sus copias. El directorio en sí se
puede replicar y todos los participantes que utilizan el DFS saben dónde están las copias del
directorio.
2.2. MAPA REDUCIDO 25

2.2 MapReduce
Mapa reducido es un estilo de computación que se ha implementado en varios sistemas,
incluida la implementación interna de Google (simplemente llamada MapReduce) y la
popular implementación de código abierto Hadoop que se puede obtener, junto con el
sistema de archivos HDFS de la Fundación Apache. Puede utilizar una implementación de
MapReduce para administrar muchos cálculos paralelos a gran escala de una manera que
sea tolerante con las fallas de hardware. Todo lo que necesita escribir son dos funciones,
llamadas Mapa y Reducir. El sistema gestiona la ejecución paralela y la coordinación de las
tareas que ejecutan Map o Reduce. El sistema también se ocupa de la posibilidad de que
una de estas tareas no se ejecute. En resumen, un cálculo de MapReduce se ejecuta de la
siguiente manera:

1. A cada una de las tareas de mapa se les asigna uno o más fragmentos de un sistema de
archivos distribuido. Estas tareas de mapa convierten el fragmento en una secuencia de
valor clave pares. La forma en que se producen los pares clave-valor a partir de los datos
de entrada está determinada por el código escrito por el usuario para la función Mapa.

2. Los pares clave-valor de cada tarea de mapa se recopilan mediante un controlador


maestro y ordenados por clave. Las claves se dividen entre todas las tareas de Reducir,
por lo que todos los pares clave-valor con la misma clave terminan en la misma tarea de
Reducir.

3. Las tareas de Reducir funcionan en una clave a la vez y combinan todos los
valores asociados con esa clave de alguna manera. La forma de combinación
de valores está determinada por el código escrito por el usuario para la función
Reducir.

La figura 2.2 sugiere este cálculo.

2.2.1 Las tareas del mapa


Consideramos que los archivos de entrada para una tarea de mapa constan de elementos, que
puede ser de cualquier tipo: una tupla o un documento, por ejemplo. Un fragmento es una
colección de elementos y ningún elemento se almacena en dos fragmentos. Técnicamente, todas
las entradas a las tareas de Mapa y las salidas de las tareas de Reducir tienen la forma de par
clave-valor, pero normalmente las claves de los elementos de entrada no son relevantes y
tendremos a ignorarlas. Insistir en este formulario para entradas y salidas está motivado por el
deseo de permitir la composición de varios procesos MapReduce.
La función Map toma un elemento de entrada como argumento y produce cero o más
pares clave-valor. Los tipos de claves y valores son arbitrarios. Además, las claves no son
"claves" en el sentido habitual; no tienen por qué ser únicos. Más bien, una tarea de mapa
puede producir varios pares clave-valor con la misma clave, incluso a partir del mismo
elemento.

Ejemplo 2.1: Ilustraremos un cálculo de MapReduce con lo que se ha convertido en la


aplicación de ejemplo estándar: contar el número de ocurrencias
26 CAPITULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Llaves con todas


sus valores
Valor-clave
pares (k, [v, w, ...])
Aporte (k, v)
trozos

Conjunto
producción

Mapa Grupo
Tareas por llaves

Reducir
Tareas

Figura 2.2: Esquema de un cálculo MapReduce

para cada palabra en una colección de documentos. En este ejemplo, el archivo de entrada
es un depósito de documentos y cada documento es un elemento. La función Map para
este ejemplo usa claves que son de tipo String (las palabras) y valores que son números
enteros. La tarea Mapa lee un documento y lo divide en su secuencia.
de palabras w 1, w 2,. . . , w norte. Luego emite una secuencia de pares clave-valor donde el
valor es siempre 1. Es decir, el resultado de la tarea Mapa para este documento es el
secuencia de pares clave-valor:

( w 1, 1), ( w 2, 1),. . . , ( w norte, 1)

Tenga en cuenta que una sola tarea de Mapa normalmente procesará muchos documentos: todos
los documentos en uno o más fragmentos. Por lo tanto, su resultado será más que la secuencia del
único documento sugerido anteriormente. Tenga en cuenta también que si una palabra w
aparece metro veces entre todos los documentos asignados a esa tarea, entonces
habrá metro pares clave-valor ( w 1) entre su salida. Una opción, que discutimos en la
Sección 2.2.4, es que esta tarea de Mapa combine estos metro pares en un solo par
w, m), pero solo podemos hacer eso porque, como veremos, las tareas Reducir
aplican una operación asociativa y conmutativa, suma, a los valores. ✷

2.2.2 Agrupación por clave


Tan pronto como las tareas de Mapa se hayan completado con éxito, los pares clave-valor
se agrupan por clave y los valores asociados con cada clave se forman en una única lista de
valores para esa clave. La agrupación la realiza el sistema, independientemente
2.2. MAPA REDUCIDO 27

de lo que hacen las tareas Mapa y Reducir. El proceso del controlador maestro sabe
cuántas tareas de Reducir habrá, digamos r tales tareas. El usuario normalmente le dice al
sistema MapReduce lo que r debiera ser. Luego, el controlador maestro elige una función
hash que toma una clave como argumento y produce un número de depósito de 0 a r - 1.
Cada clave generada por una tarea de mapa tiene un hash y su par clave-valor se coloca en
uno de r archivos locales. Cada archivo está destinado a uno de los r Reducir tareas. 1

Para realizar la agrupación por clave y distribución a las tareas de Reducir, el


controlador maestro fusiona los archivos de cada tarea de Mapa que están destinados a
una tarea de Reducir en particular y alimenta el archivo combinado a ese proceso como
una secuencia de clave / lista de valores pares. Es decir, para cada clave k, la entrada al
Reducir la tarea que maneja la clave k es un par de la forma ( k, [v 1, v 2,. . . , v norte]), dónde
( k, v 1), ( k, v 2),. . . , ( k, v norte) son todos los pares clave-valor con clave k provenientes de todas las
tareas del Mapa.

2.2.3 Las tareas de reducción


El argumento de la función Reducir es un par que consta de una clave y su lista de
valores asociados. La salida de la función Reducir es una secuencia de cero o más
pares clave-valor. Estos pares clave-valor pueden ser de un tipo diferente de los
enviados desde Asignar tareas a Reducir tareas, pero a menudo son del mismo tipo.
Nos referiremos a la aplicación de la función Reducir a una sola tecla y su lista de
valores asociada como un reductor.
Una tarea de Reducir recibe una o más claves y sus listas de valores asociadas. Es
decir, una tarea de Reducir ejecuta uno o más reductores. Las salidas de todas las
tareas de Reducir se fusionan en un solo archivo.

Ejemplo 2.2: Continuemos con el ejemplo del recuento de palabras del ejemplo 2.1. La
función Reducir simplemente suma todos los valores. La salida de un reductor consta de la
palabra y la suma. Por lo tanto, el resultado de todas las tareas de Reducir es una
secuencia de ( w, m) pares, donde w es una palabra que aparece al menos una vez entre
todos los documentos de entrada y metro es el número total de apariciones de w entre
esos documentos. ✷

2.2.4 Combinadores
A veces, una función Reducir es asociativa y conmutativa. Es decir, los valores a
combinar se pueden combinar en cualquier orden, con el mismo resultado. La suma
realizada en el ejemplo 2.2 es un ejemplo de una operación asociativa y conmutativa.
No importa cómo ordenemos o agrupamos una lista de
números v 1, v 2,. . . , v norte; la suma será la misma.
Cuando la función Reducir es asociativa y conmutativa, podemos presionar
algo de lo que hacen los reductores con las tareas del mapa. Por ejemplo, en lugar de cada
1 Opcionalmente, los usuarios pueden especificar su propia función hash u otro método para asignar claves
para Reducir tareas. Sin embargo, sea cual sea el algoritmo que se utilice, cada tecla se asigna a una y solo una
tarea de Reducir.
28 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Reductores, tareas reducidas, nodos de cálculo y sesgo

Si queremos el máximo paralelismo, entonces podríamos usar una tarea Reducir para
ejecutar cada reductor, es decir, una sola tecla y su lista de valores asociada. Además,
podríamos ejecutar cada tarea de Reducir en un nodo de cálculo diferente, por lo que
todas se ejecutarían en paralelo. Este plan no suele ser el mejor. Un problema es que hay
una sobrecarga asociada con cada tarea que creamos, por lo que es posible que
deseemos mantener el número de tareas de Reducir más bajo que el número de claves
diferentes. Además, a menudo hay muchas más claves que nodos de cómputo
disponibles, por lo que no obtendríamos ningún beneficio de una gran cantidad de tareas
de Reducir.
En segundo lugar, a menudo hay una variación significativa en las longitudes de las
listas de valores para diferentes claves, por lo que los diferentes reductores toman
diferentes cantidades de tiempo. Si hacemos de cada reductor una tarea de Reducir
separada, entonces las tareas mismas exhibirán sesgar - una diferencia significativa en la
cantidad de tiempo que toma cada uno. Podemos reducir el impacto del sesgo utilizando
menos tareas de Reducir que reductores. Si las claves se envían al azar a las tareas de
Reducir, podemos esperar que haya un promedio del tiempo total requerido por las
diferentes tareas de Reducir. Podemos reducir aún más el sesgo utilizando más tareas
Reducir que nodos de cálculo. De esa manera, las tareas de Reducir largas pueden ocupar
un nodo de cómputo por completo, mientras que varias tareas de Reducir más cortas
pueden ejecutarse secuencialmente en un solo nodo de cómputo.

La tarea de mapeo del ejemplo 2.1 produce muchos pares ( w 1), ( w 1),. . ., podríamos
aplicar la función Reducir dentro de cada tarea de Mapa, antes de que los resultados
de las tareas de Mapa estén sujetos a agrupación y agregación. Estos pares clave-
valor serían reemplazados por un par con clave w y valor igual a la suma de todos los
1 en todos esos pares. Es decir, los pares con clave w generado por una sola tarea de
mapa sería reemplazado por un par ( w, m), dónde metro es el número de veces que
w aparece entre los documentos manejados por esta tarea de Mapa. Tenga en
cuenta que todavía es necesario agrupar y agregar y pasar el resultado a las tareas
de Reducir, ya que normalmente habrá un par clave-valor con clave w
provenientes de cada una de las tareas del Mapa.

2.2.5 Detalles de la ejecución de MapReduce


Consideremos ahora con más detalle cómo se ejecuta un programa que usa MapReduce. La
Figura 2.3 ofrece un esquema de cómo interactúan los procesos, tareas y archivos.
Aprovechando una biblioteca proporcionada por un sistema MapReduce como Hadoop, el
programa de usuario bifurca un proceso de controlador maestro y algunos procesos de trabajo
en diferentes nodos de cómputo. Normalmente, un trabajador maneja las tareas del mapa (un
Trabajador del mapa) o Reducir tareas (a Reducir trabajador), pero no ambos.
El Maestro tiene muchas responsabilidades. Uno es crear una serie de
2.2. MAPA REDUCIDO 29

Usuario
Programa

tenedor

tenedor tenedor

Maestría

asignar
asignar
Mapa
Reducir

Trabajador
Trabajador

Trabajador

Trabajador

Aporte Trabajador

Datos Producción

Intermedio Expediente

Archivos

Figura 2.3: Resumen de la ejecución de un programa MapReduce

Mapear tareas y algunas tareas de Reducir, estos números son seleccionados por el
programa de usuario. Estas tareas serán asignadas a los procesos Worker por el Maestro.
Es razonable crear una tarea de Mapa para cada fragmento de los archivos de entrada,
pero es posible que deseemos crear menos tareas de Reducir. La razón para limitar el
número de tareas de Reducir es que es necesario que cada tarea de Mapa cree un archivo
intermedio para cada tarea de Reducir, y si hay demasiadas tareas de Reducir, el número
de archivos intermedios aumenta.

El maestro realiza un seguimiento del estado de cada tarea de mapa y reducción (inactiva,
en ejecución en un trabajador en particular o completada). Un proceso de trabajador informa al
maestro cuando finaliza una tarea, y el maestro programa una nueva tarea para ese proceso de
trabajador.

A cada tarea de Mapa se le asigna uno o más fragmentos de los archivos de entrada y
ejecuta en él el código escrito por el usuario. La tarea Mapa crea un archivo para cada
tarea Reducir en el disco local del Trabajador que ejecuta la tarea Mapa. Se informa al
Maestro de la ubicación y tamaño de cada uno de estos archivos, y la tarea Reducir para la
que está destinado cada uno. Cuando el maestro asigna una tarea de reducción a un
proceso de trabajador, a esa tarea se le asignan todos los archivos que forman su entrada.
La tarea Reducir ejecuta código escrito por el usuario y escribe su salida en un archivo que
es parte del sistema de archivos distribuido circundante.
30 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

2.2.6 Hacer frente a las fallas de los nodos


Lo peor que puede suceder es que falle el nodo de cálculo en el que se está ejecutando el
maestro. En este caso, se debe reiniciar todo el trabajo de MapReduce. Pero solo este
nodo puede hacer caer todo el proceso; otras fallas serán administradas por el maestro y
el trabajo de MapReduce se completará eventualmente.
Suponga que falla el nodo de cálculo en el que reside un trabajador de mapas. Esta
falla será detectada por el maestro, porque periódicamente hace ping a los procesos del
trabajador. Todas las tareas del mapa que se asignaron a este trabajador deberán
rehacerse, incluso si se han completado. La razón para rehacer las tareas de Mapa
completadas es que su salida destinada a las tareas de Reducir reside en ese nodo de
cálculo y ahora no está disponible para las tareas de Reducir. El Maestro establece el
estado de cada una de estas tareas del Mapa en inactivo y las programará en un
Trabajador cuando haya uno disponible. El Maestro también debe informar a cada tarea
de Reducir que la ubicación de su entrada de esa tarea de Mapa ha cambiado.
Tratar una falla en el nodo de un trabajador de Reducir es más simple. El maestro simplemente
establece el estado de las tareas de Reducir que se están ejecutando actualmente en inactivo. Estos se
reprogramarán en otro trabajador de Reducir más adelante.

2.2.7 Ejercicios para la sección 2.2


Ejercicio 2.2.1: Suponga que ejecutamos el programa MapReduce de recuento de palabras
descrito en esta sección en un repositorio grande, como una copia de la Web. Usaremos
100 tareas de Mapa y algunas tareas de Reducir.

(a) Suponga que no usamos un combinador en las tareas de Mapa. ¿Espera que haya un sesgo
significativo en los tiempos que tardan los distintos reductores en procesar su lista de
valores? ¿Por qué o por qué no?

(b) Si combinamos los reductores en un pequeño número de tareas de Reducir,


digamos 10 tareas, al azar, ¿espera que el sesgo sea significativo? ¿Qué pasa si
combinamos los reductores en 10,000 tareas de Reducir?

! ( c) Suponga que usamos un combinador en las 100 tareas del Mapa. ¿Espera que el sesgo sea
significativo? ¿Por qué o por qué no?

2.3 Algoritmos que utilizan MapReduce


MapReduce no es una solución a todos los problemas, ni siquiera a todos los problemas que
pueden usar de manera rentable muchos nodos de cómputo que operan en paralelo. Como
mencionamos en la Sección 2.1.2, todo el entorno del sistema de archivos distribuidos tiene
sentido sólo cuando los archivos son muy grandes y rara vez se actualizan en su lugar. Por
ejemplo, no esperaríamos usar un DFS o una implementación de MapReduce para administrar
las ventas minoristas en línea, aunque un gran minorista en línea como Amazon.com usa miles
de nodos de cómputo cuando procesa solicitudes a través de la Web. El motivo es que las
principales operaciones sobre los datos de Amazon implican responder a búsquedas
2.3. ALGORITMOS QUE UTILIZAN MAPREDUCE 31

para productos, registro de ventas, etc., procesos que implican relativamente pocos
cálculos y que modifican la base de datos. 2 Por otro lado, Amazon podría usar MapReduce
para realizar ciertas consultas analíticas en grandes cantidades de datos, como encontrar
para cada usuario aquellos usuarios cuyos patrones de compra fueran más similares.

El propósito original para el cual se creó la implementación de MapReduce en


Google era ejecutar multiplicaciones de matriz-vector muy grandes, como se necesita
en el cálculo de PageRank (Ver Capítulo 5). Veremos que los cálculos de matriz-vector
y matriz-matriz encajan muy bien en el estilo de computación MapReduce. Otra clase
importante de operaciones que pueden usar MapReduce de manera efectiva son las
operaciones de álgebra relacional. También examinaremos la ejecución de
MapReduce de estas operaciones.

2.3.1 Multiplicación de matriz-vector por MapReduce


Supongamos que tenemos un norte × norte matriz METRO, cuyo elemento en fila I y columna j es
denotado metro ij. Supongamos que también tenemos un vector v de longitud norte, cuyo j el
elemento es v j. Entonces el producto matriz-vector es el vector X de longitud norte, cuyo I th
elemento X I es dado por
Xnorte

X yo = metro ij v j

j=1

Si n = 100, no queremos para utilizar un DFS o MapReduce para este cálculo.


Pero este tipo de cálculo es en el corazón del ranking de páginas web que
continúa en los motores de búsqueda, y allí, norte es del orden de billones. 3 Nos deja
primero asume que norte es grande, pero no tanto que el vector v no puede caber en la memoria y, en la principal

por lo tanto, estar disponible para todas las tareas del Mapa.
La matriz METRO y el vector v cada uno se almacenará en un archivo del DFS.
Suponemos que las coordenadas fila-columna de cada elemento de la matriz serán
detectables, ya sea desde su posición en el archivo, o porque está almacenado con explícita
coordenadas, como un triple ( yo, j, m ij). También asumimos la posición de elemento v
j en
el vector v será detectable de forma análoga.
La función del mapa: La función Mapa está escrita para aplicarse a un elemento de
METRO. Sin embargo, si v aún no se lee en la memoria principal en el nodo de cálculo que
ejecuta una tarea de mapa, entonces v se lee por primera vez, en su totalidad, y posteriormente
estará disponible para todas las aplicaciones de la función de Mapa realizadas en esta tarea de
Mapa. Cada tarea de mapa operará en una parte de la matriz METRO. De cada matriz
elemento metro ij produce el par clave-valor ( soy ij v j). Por lo tanto, todos los términos del
suma que componen el componente X I del producto matriz-vector obtendrá la
misma clave, I.
2 Recuerde que incluso mirar un producto que no compra hace que Amazon recuerde que lo miró.

3 La matriz es escasa, con un promedio de 10 a 15 elementos distintos de cero por fila, ya que
matriz representa los enlaces en la Web, con metro ij distinto de cero si y solo si hay un enlace desde la página j
a la página I. Tenga en cuenta que no hay forma de que podamos almacenar una matriz densa cuyo lado sea
10 12, ya que tendría 10 24 elementos.
32 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

La función de reducción: La función Reducir simplemente suma todos los valores


asociados con una clave determinada I. El resultado será un par ( yo, x I).

2.3.2 Si el vector v no cabe en la memoria principal

Sin embargo, es posible que el vector v es tan grande que no cabe en su totalidad en
la memoria principal. No es necesario que v caben en la memoria principal en un
nodo de cálculo, pero si no es así, habrá una gran cantidad de accesos al disco a
medida que movamos partes del vector a la memoria principal para multiplicar
componentes por elementos de la matriz. Por tanto, como alternativa, podemos
dividir la matriz en vertical rayas de igual ancho y divida el vector en un número igual
de franjas horizontales, de la misma altura. Nuestro objetivo es utilizar suficientes
franjas para que la parte del vector en una franja pueda caber cómodamente en la
memoria principal de un nodo de cálculo. La figura 2.4 sugiere cómo se ve la
partición si la matriz y el vector se dividen cada uno en cinco franjas.

Figura 2.4: División de una matriz y un vector en cinco franjas

los I La franja de la matriz multiplica solo los componentes del I th raya del vector. Por
tanto, podemos dividir la matriz en un archivo para cada franja y hacer lo mismo con el
vector. A cada tarea de Mapa se le asigna un fragmento de una de las franjas de la matriz y
obtiene toda la franja correspondiente del vector. Las tareas de Mapa y Reducción pueden
actuar exactamente como se describe en la Sección 2.3.1 para el caso en el que las tareas
de Mapa obtienen el vector completo.
Retomaremos la multiplicación matriz-vector usando MapReduce nuevamente en
la Sección 5.2. Allí, debido a la aplicación particular (cálculo de PageRank), tenemos
una restricción adicional de que el vector de resultado debe dividirse de la misma
manera que el vector de entrada, por lo que la salida puede convertirse en la entrada
para otra iteración de la multiplicación matriz-vector. Veremos allí que la mejor
estrategia consiste en dividir la matriz METRO en bloques cuadrados, en lugar de
rayas.
2.3. ALGORITMOS QUE UTILIZAN MAPREDUCE 33

2.3.3 Operaciones de álgebra relacional


Hay una serie de operaciones sobre datos a gran escala que se utilizan en consultas de bases de
datos. Muchas aplicaciones de bases de datos tradicionales implican la recuperación de
pequeñas cantidades de datos, aunque la base de datos en sí puede ser grande. Por ejemplo,
una consulta puede solicitar el saldo bancario de una cuenta en particular. Estas consultas no
son aplicaciones útiles de MapReduce.
Sin embargo, hay muchas operaciones sobre datos que pueden describirse fácilmente en
términos de las primitivas comunes de consulta de base de datos, incluso si las consultas en sí
no se ejecutan dentro de un sistema de gestión de base de datos. Por lo tanto, un buen punto de
partida para explorar aplicaciones de MapReduce es considerar las operaciones estándar sobre
relaciones. Suponemos que está familiarizado con los sistemas de bases de datos, el lenguaje de
consulta SQL y el modelo relacional, pero para revisar, un relación es una tabla con encabezados
de columna llamada atributos. Las filas de la relación se llaman
tuplas. El conjunto de atributos de una relación se llama su esquema. A menudo escribimos
una expresión como REAL ACADEMIA DE BELLAS ARTES 1, A decir que el nombre de la relación es R y es
2,. . . , A norte) a los atributos son A 1, A 2,. . . , A norte.

De Para
url1 url2
url1 url3
url2 url3
url2 url4
··· ···

Figura 2.5: Relación Enlaces Consiste en el conjunto de pares de URL, de modo que la
primera tiene uno o más enlaces a la segunda.

Ejemplo 2.3: En la figura 2.5 vemos parte de la relación Enlaces que describe la
estructura de la Web. Hay dos atributos, De y Para. Una fila, o tupla, de la relación es
un par de URL de modo que hay al menos un enlace desde la primera URL a la
segunda. Por ejemplo, la primera fila de la figura 2.5 es el par ( url 1, url 2). Esta tupla
dice la página web url 1 tiene un enlace a la página url 2. Si bien hemos mostrado
solo cuatro tuplas, la relación real de la Web, o la parte de ella que sería almacenada
por un motor de búsqueda típico, tiene billones de tuplas. ✷

Una relación, por grande que sea, se puede almacenar como un archivo en un sistema de archivos
distribuido. Los elementos de este archivo son las tuplas de la relación.
Hay varias operaciones estándar sobre relaciones, a menudo denominadas álgebra
relacional, que se utilizan para implementar consultas. Las consultas en sí mismas suelen
estar escritas en SQL. Las operaciones de álgebra relacional que discutiremos son:

1. Selección: Aplicar una condición C a cada tupla en la relación y producen como


salida solo aquellas tuplas que satisfacen C. El resultado de esta selección es
denotado σ C( R).
34 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

2. Proyección: Para algún subconjunto S de los atributos de la relación, producen


de cada tupla sólo los componentes de los atributos en S. El resultado
de esta proyección se denota π S( R).

3. Unión, intersección, y Diferencia: Estas operaciones de conjuntos bien conocidas se


aplican a los conjuntos de tuplas en dos relaciones que tienen el mismo esquema.
También hay versiones bag (multiset) de las operaciones en SQL, con de fi niciones
algo poco intuitivas, pero no entraremos en las versiones bag de estas operaciones
aquí.

4. Unión natural: Dadas dos relaciones, compare cada par de tuplas, una de cada
relación. Si las tuplas concuerdan en todos los atributos que son comunes a los dos
esquemas, entonces genere una tupla que tenga componentes para cada uno de
los atributos en cualquiera de los esquemas y concuerde con las dos tuplas en cada
atributo. Si las tuplas no están de acuerdo con uno o más atributos compartidos, no
produzca nada a partir de este par de tuplas. La unión natural de relaciones R
y S se denota R ⊲⊳ S. Si bien discutiremos la ejecución solo de la combinación
natural con MapReduce, todos equijoins Las combinaciones donde la condición de
acuerdo de tupla implica la igualdad de atributos de las dos relaciones que no
necesariamente tienen el mismo nombre) se pueden ejecutar de la misma manera.
Daremos una ilustración en el ejemplo 2.4.

5. Agrupamiento y Agregación: 4 Dada una relación R, particiona sus tuplas de acuerdo


con sus valores en un conjunto de atributos GRAMO, llamó al atributos de
agrupación. Luego, para cada grupo, agregue los valores en ciertos otros atributos.
Las agregaciones normalmente permitidas son SUM, COUNT, AVG, MIN y MAX, con
los significados obvios. Tenga en cuenta que MIN y MAX requieren que los atributos
agregados tengan un tipo que se pueda comparar,
por ejemplo, números o cadenas, mientras que SUM y AVG requieren que el tipo permita
operaciones aritméticas, normalmente solo números. COUNT se puede realizar en datos
de cualquier tipo. Denotamos una operación de agrupación y agregación en
una relación R por γ X( R), dónde X es una lista de elementos que son cada uno

(a) Un atributo de agrupación, o

(b) Una expresión θ (A), dónde θ es una de las cinco operaciones de agregación
como SUM, y A es un atributo que no se encuentra entre los atributos de
agrupación.

El resultado de esta operación es una tupla para cada grupo. Esa tupla tiene un
componente para cada uno de los atributos de agrupación, con el valor común
a las tuplas de ese grupo. También tiene un componente para cada
agregación, con el valor agregado para ese grupo. Veremos una ilustración en
el ejemplo 2.5.
4 Algunas descripciones del álgebra relacional no incluyen estas operaciones y, de hecho, no formaban
parte de la definición original de este álgebra. Sin embargo, estas operaciones son tan importantes en SQL que
los tratamientos modernos de álgebra relacional las incluyen.
2.3. ALGORITMOS QUE UTILIZAN MAPREDUCE 35

Ejemplo 2.4: Intentemos encontrar los caminos de longitud dos en la Web, usando la
relación Enlaces de la figura 2.5. Es decir, queremos encontrar los triples de las URL ( u, v,
w) tal que haya un enlace desde tu para v y un enlace de v para w. Básicamente, queremos
aprovechar la unión natural de Enlaces consigo mismo, pero primero debemos imaginar
que son dos relaciones, con diferentes esquemas, para poder describir la conexión
deseada como una unión natural. Por tanto, imagina que hay dos copias de Enlaces, a
saber L 1 ( U 1, U 2) y L 2 ( U 2, U 3). Ahora, si calculamos L 1 ⊲⊳ L 2, tendremos
exactamente lo que queremos. Es decir, para cada tupla t 1 de L 1 (es decir, cada tupla de
Enlaces) y cada tupla t 2 de L 2 (otra tupla de Enlaces, posiblemente incluso la misma
tupla), vea si su U 2 componentes son iguales. Tenga en cuenta que estos componentes
son el segundo componente de t 1 y el primer componente de
t 2. Si estos dos componentes concuerdan, genere una tupla para el resultado, con el
esquema ( U 1, U 2, U 3). Esta tupla consta del primer componente de t 1, el segundo
componente de t 1 (que debe ser igual al primer componente de t 2), y el segundo
componente de t 2.
Es posible que no queramos la ruta completa de longitud dos, sino solo los pares ( u,
w) de URL de modo que haya al menos una ruta desde tu para w de longitud dos. Si
entonces, podemos proyectar los componentes intermedios calculando π U 1, U 3 ( L 1 ⊲⊳ L 2).

Ejemplo 2.5: Imagine que un sitio de redes sociales tiene una relación

Amigos (usuario, amigo)

Esta relación tiene tuplas que son pares ( a, b) tal que B es amigo de una. Es posible
que el sitio desee desarrollar estadísticas sobre la cantidad de amigos que tienen los
miembros. Su primer paso sería calcular el número de amigos de cada usuario. Esta
operación se puede realizar agrupando y agregando, específicamente

γ Usuario, COUNT (amigo) ( Amigos)

Esta operación agrupa todas las tuplas por el valor de su primer componente, por lo
que hay un grupo para cada usuario. Luego, para cada grupo se realiza el conteo del
número de amigos de ese usuario. El resultado será una tupla para cada grupo, y una
tupla típica se vería como (Sally, 300), si el usuario "Sally" tiene 300 amigos. ✷

2.3.4 Cálculo de selecciones por MapReduce


Las selecciones realmente no necesitan todo el poder de MapReduce. Se pueden hacer
más convenientemente en la parte del mapa solo, aunque también se pueden hacer solo
en la parte de reducción. Aquí hay una implementación de MapReduce de selección
σ C( R).
La función del mapa: Para cada tupla t en R, prueba si satisface C. Si es así, genere el
par clave-valor ( t, t). Es decir, tanto la clave como el valor son t. Si t no satisface C,
luego el mapeador para t no produce nada.
36 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

La función de reducción: La función Reducir es la identidad. Simplemente pasa cada


par clave-valor a la salida.

Tenga en cuenta que la salida no es exactamente una relación, porque tiene pares clave-
valor. Sin embargo, se puede obtener una relación utilizando solo los componentes de valor (o
solo los componentes clave) de la salida.

2.3.5 Cálculo de proyecciones con MapReduce


La proyección se realiza de manera similar a la selección. Sin embargo, debido a que la
proyección puede hacer que la misma tupla aparezca varias veces, la función Reducir debe
eliminar duplicados. Podemos calcular π S( R) como sigue.
La función del mapa: Para cada tupla t en R, construir una tupla t ′ eliminando de t
aquellos componentes cuyos atributos no están en S. Genere el par clave-valor ( t ′, t ′).

La función de reducción: Para cada clave t ′ producido por cualquiera de las tareas del
Mapa, habrá uno o más pares clave-valor ( t ′, t ′). Una vez que el sistema agrupa los pares de
valores clave por clave, la función Reducir cambia ( t ′, [ t ′, t ′,. . . , t ′]) dentro ( t ′, t ′), por lo que
produce exactamente un par ( t ′, t ′) para esta llave t ′.

Observe que la operación Reducir es eliminación de duplicados. Esta operación es asociativa


y conmutativa, por lo que un combinador asociado con cada tarea de Mapa puede eliminar
cualquier duplicado que se produzca localmente. Sin embargo, las tareas de Reducir aún son
necesarias para eliminar dos tuplas idénticas provenientes de diferentes tareas de Mapa.

2.3.6 Unión, intersección y diferencia por MapReduce


Primero, considere la unión de dos relaciones. Supongamos relaciones R y S tienen el
mismo esquema. A las tareas de mapa se les asignarán fragmentos de R o S; no importa
cuál. Las tareas de Mapa no hacen nada más que pasar sus tuplas de entrada como pares
clave-valor a las tareas de Reducir. Este último solo necesita eliminar duplicados en cuanto
a proyección.
La función del mapa: Gire cada tupla de entrada t en un par clave-valor ( t, t).
La función de reducción: Asociado a cada clave t habrá uno o dos valores. Producir
salida ( t, t) en cualquier caso.

Para calcular la intersección, podemos usar la misma función de Mapa. Sin embargo, la
función Reducir debe producir una tupla solo si ambas relaciones tienen la tupla. Si la llave
t tiene una lista de dos valores [ t, t] asociado con él, luego la tarea Reducir para t debería
producir t, t). Sin embargo, si la lista de valores asociada con la clave
t es solo [ t], luego uno de R y S Está perdido t, por lo que no queremos producir una
tupla para la intersección.
La función del mapa: Gire cada tupla t en un par clave-valor ( t, t).
La función de reducción: Si clave t tiene lista de valores [ t, t], luego producir t, t). De lo
contrario, no produzca nada.
2.3. ALGORITMOS QUE UTILIZAN MAPREDUCE 37

La diferencia R - S requiere un poco más de reflexión. La única forma en que una tupla
t puede aparecer en la salida es si está en R pero no en S. La función Mapa puede
pasar tuplas desde R y S a través, pero debe informar a la función Reducir si la tupla
proviene de R o S. Por tanto, usaremos la relación como el valor asociado con la clave
t. Aquí hay una especificación para las dos funciones.
La función del mapa: Para una tupla t en R, producir par clave-valor ( t, R), y para una
tupla t en S, producir par clave-valor ( t, S). Tenga en cuenta que la intención es que el
valor sea el nombre de R o S ( o mejor, un solo bit que indica si la relación es R o S),
no toda la relación.
La función de reducción: Para cada clave t, si la lista de valores asociada es [ R], luego
producir t, t). De lo contrario, no produzca nada.

2.3.7 Cálculo de la unión natural mediante MapReduce


La idea detrás de la implementación de la unión natural a través de MapReduce se puede
ver si observamos el caso específico de la unión R (A, B) con S (B, C). 5 Debemos encontrar
tuplas que estén de acuerdo con su B componentes, que es el segundo componente de
tuplas de R y el primer componente de tuplas de S. Usaremos el B- valor de tuplas de
cualquier relación como clave. El valor será el otro componente y el nombre de la relación,
por lo que la función Reducir puede saber de dónde vino cada tupla.

La función del mapa: Para cada tupla ( a, b) de R, producir el par clave-valor


b, (R, a). Para cada tupla ( antes de Cristo) de S, producir el par clave-valor b, (S, c).
La función de reducción: Cada valor clave B se asociará con una lista de pares que
son de la forma ( R, a) o ( S, c). Construya todos los pares que constan de uno con el
primer componente R y el otro con el primer componente S, decir ( R, a) y ( S, c). El
resultado de esta lista de claves y valores es una secuencia de pares clave-valor. La
clave es irrelevante. Cada valor es uno de los triples ( a B C) tal que R, a)
y ( S, c) están en la lista de entrada de valores para la clave B.

El mismo algoritmo funciona si las relaciones tienen más de dos atributos. Tu


puedes pensar en A como representando todos esos atributos en el esquema de R
pero no S. B representa los atributos en ambos esquemas, y C representa atributos
solo en el esquema de S. La clave para una tupla de R o S es la lista de valores en
todos los atributos que están en los esquemas de ambos R y S. El valor de una tupla
de R es el nombre R junto con los valores de todos los atributos pertenecientes a
R pero no para S, y el valor de una tupla de S es el nombre S junto con los valores de
los atributos pertenecientes a S pero no R.
La función Reducir examina todos los pares clave-valor con una clave determinada y
combina esos valores de R con esos valores de S de todas las formas posibles. De cada
emparejamiento, la tupla producida tiene los valores de R, los valores clave y los valores de
S.
5 Si está familiarizado con la implementación de la base de datos, reconocerá la implementación de
MapReduce de join como la clásica combinación de hash paralela.
38 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

2.3.8 Agrupación y agregación por MapReduce


Como hicimos para la combinación, discutiremos aquí solo el ejemplo mínimo de
agrupación y agregación, donde hay un atributo de agrupación ( A), un atributo
agregado ( B), y un atributo ( C) que no está agrupado ni agregado.
Dejar R (A, B, C) ser una relación a la que aplicamos el operador γ A, θ (B) ( R). Map
realizará la agrupación, mientras que Reducir realizará la agregación.
La función del mapa: Para cada tupla ( a B C) producir el par clave-valor ( a, b).
La función de reducción: Cada clave a representa un grupo. Aplicar la agregación
operador θ a la lista [ B 1, B 2,. . . , B norte] de B- valores asociados con la clave una. La
salida es el par ( a, x), dónde X es el resultado de aplicar θ a la lista. Para
ejemplo, si θ es SUM, entonces x = b 1 + B 2 + · · · + B norte, y si θ es MAX, entonces X es el más
grande de B 1, B 2,. . . , B norte.

Si hay varios atributos de agrupación, la clave es la lista de valores de una tupla


para todos estos atributos. Si hay más de una agregación, la función Reducir aplica
cada uno de ellos a la lista de valores asociados con una clave determinada y produce
una tupla que consta de la clave, incluidos los componentes de todos los atributos de
agrupación si hay más de uno, seguido de los resultados de cada una de las
agregaciones.

2.3.9 Multiplicación de matrices


Si METRO es una matriz con elemento metro ij en fila I y columna j, y norte es una matriz
con elemento norte jk en fila j y columna k, entonces el producto P = MN es el
matriz PAG con elemento pag ik en fila I and
X columna k, dónde

pag ik = metro ij norte jk

Se requiere que el número de columnas de METRO es igual al número de filas de


NORTE, así que la suma se acabó j tiene sentido.
Podemos pensar en una matriz como una relación con tres atributos: el número de
fila, el número de columna y el valor en esa fila y columna. Por lo tanto, podríamos ver
matriz METRO como una relación M (yo, j, v), con tuplas yo, j, m ij), y pudimos ver
matriz norte como una relación N (J, K, W), con tuplas j, k, n jk). Como las matrices grandes a menudo son
escasas (en su mayoría ceros), y como podemos omitir las tuplas para los elementos de la matriz
que son 0, esta representación relacional suele ser muy buena para una matriz
grande. Sin embargo, es posible que yo, j, y k están implícitos en la posición de un
elemento de matriz en el archivo que lo representa, en lugar de estar escritos
explícitamente con el elemento en sí. En ese caso, la función Mapa deberá diseñarse
para construir el Yo, j y K componentes de tuplas desde la posición de los datos.
El producto Minnesota es casi una unión natural seguida de agrupación y
agregación. Es decir, la unión natural de M (yo, j, v) y N (J, K, W), teniendo solo
atributo J en común, produciría tuplas ( yo, j, k, v, w) de cada tupla yo, j, v) en METRO y
tupla j, k, w) en NORTE. Esta tupla de cinco componentes representa la
2.3. ALGORITMOS QUE UTILIZAN MAPREDUCE 39

par de elementos de la matriz metro ij, norte jk). En cambio, lo que queremos es el producto
de estos elementos, es decir, la tupla de cuatro componentes ( yo, j, k, v × w), por eso
representa el producto metro ij norte jk. Una vez que tenemos esta relación como resultado
de una operación MapReduce, podemos realizar agrupaciones y agregaciones, con I y
K como los atributos de agrupación y la suma de V × W como la agregación. Es decir,
podemos implementar la multiplicación de matrices como la cascada de dos operaciones
MapReduce, como sigue. Primero:
La función del mapa: Para cada elemento de la matriz metro ij, producir el par clave-valor
j, (M, yo, m ij). Asimismo, para cada elemento de la matriz norte jk, producir el valor clave
par j, (N, k, n jk). Tenga en cuenta que METRO y norte en los valores no están las matrices en
sí mismas. Más bien son nombres de las matrices o, más precisamente, un solo
bit que indica si el elemento proviene de METRO o N ( como mencionamos con
respecto a la función Map similar que usamos para la unión natural) :.
La función de reducción: Para cada clave j, examine su lista de valores asociados.
Por cada valor que proviene de METRO, decir ( M, yo, m ij), y cada valor que viene de
NORTE, decir ( N, k, n jk), producir un par clave-valor con clave igual a ( yo, k) y valor
igual al producto de estos elementos, metro ij norte jk.
Ahora, realizamos una agrupación y agregación mediante otra operación MapReduce
aplicada a la salida de la primera operación MapReduce.
La función del mapa: Esta función es solo la identidad. Es decir, para cada elemento de
entrada con clave ( yo, k) y valor v, producir exactamente este par clave-valor.
La función de reducción: Para cada tecla ( yo, k), producir la suma de la lista de
valores asociados con esta clave. El resultado es un par ( yo, k), v, dónde v es el valor
del elemento en fila I y columna k de la matriz P = MN.

2.3.10 Multiplicación de matrices con un paso de MapReduce


A menudo hay más de una forma de utilizar MapReduce para resolver un problema. Es posible
que desee utilizar solo una pasada de MapReduce para realizar la multiplicación de matrices
P = MN. 6 Es posible hacerlo si ponemos más trabajo en las dos funciones. Comience
usando la función Mapa para crear los conjuntos de elementos de la matriz que se
necesitan para calcular cada elemento de la respuesta PAG . Observe que un elemento de
METRO o norte contribuye a muchos elementos del resultado, por lo que un elemento de
entrada se convertirá en muchos pares clave-valor. Las claves serán pares ( yo, k), dónde I es una
fila de METRO y k es una columna de NORTE. Aquí hay una sinopsis de las funciones Mapa y
Reducir.
La función del mapa: Para cada elemento metro ij de METRO, producir todos los pares
clave-valor ( yo, k), (M, j, m ij) por k = 1, 2,. . . hasta el número de columnas de
NORTE. Del mismo modo, para cada elemento norte jk de NORTE, producir todos los pares clave-valor
( yo, k), (N, j, n jk) por yo = 1, 2,. . . hasta el número de filas de METRO. Como antes,
METRO y norte son realmente bits para decir cuál de las dos matrices viene un valor
de.
6 Sin embargo, mostramos en la Sección 2.6.7 que dos pasadas de MapReduce suelen ser mejores que una
para la multiplicación de matrices.
40 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

La función de reducción: Cada tecla ( yo, k) tendrá una lista asociada con todos
Los valores ( M, j, m ij) y ( N, j, n jk), para todos los valores posibles de j. La función
Reducir necesita conectar los dos valores de la lista que tienen el mismo valor de
j, para cada j. Una forma sencilla de realizar este paso es ordenar por j los valores que comienzan con
METRO y ordenar por j los valores que comienzan con NORTE, en listas separadas. los j th
los valores de cada lista deben tener sus terceros componentes, metro ij y norte jk extraído
y multiplicado. Luego, estos productos se suman y el resultado se empareja con
( yo, k) en la salida de la función Reducir.

Puede notar que si una fila de la matriz METRO o una columna de la matriz norte
es tan grande que no cabe en la memoria principal, entonces las tareas de Reducir se verán
obligadas a usar una ordenación externa para ordenar los valores asociados con una clave
determinada ( yo, k). Sin embargo, en ese caso, las matrices mismas son tan grandes, tal vez 10 20

elementos, que es poco probable que intentemos este cálculo si las matrices fueran
densas. Si son escasos, esperaríamos que se asociaran muchos menos valores con
cualquier clave, y sería factible hacer la suma de productos en la memoria principal.

2.3.11 Ejercicios para la sección 2.3


Ejercicio 2.3.1: Diseñe algoritmos MapReduce para tomar un archivo muy grande de
enteros y producir como salida:

(a) El número entero más grande.

(b) El promedio de todos los números enteros.

(c) El mismo conjunto de números enteros, pero cada número entero aparece solo una vez.

! ( d) El recuento del número de enteros distintos en la entrada.

En cada parte, puede asumir que la clave de cada par de salida será ignorada o
descartada.

Ejercicio 2.3.2: Nuestra formulación de la multiplicación matriz-vector asumió que la


matriz METRO era cuadrado. Generalizar el algoritmo al caso donde METRO es un
r- por- C matriz para cierto número de filas r y columnas C.

! Ejercicio 2.3.3: En la forma de álgebra relacional implementada en SQL, las relaciones


no son conjuntos, sino bolsas; es decir, las tuplas pueden aparecer más de una vez.
Hay definiciones extendidas de unión, intersección y diferencia para bolsas, que
definiremos a continuación. Escriba algoritmos MapReduce para calcular las
siguientes operaciones en bolsas R y S:

(a) Unión de Bolsa, definido como la bolsa de tuplas en la que tupla t aparece la
suma del número de veces que aparece en R y S.

(B) Intersección de bolsa, definido como la bolsa de tuplas en la que tupla t aparece
el mínimo de veces que aparece en R y S.
2.4. EXTENSIONES A MAPREDUCE 41

(C) Diferencia de bolsa, definido como la bolsa de tuplas en la que el número de


veces que una tupla t aparece es igual al número de veces que aparece en R
menos el número de veces que aparece en S. Una tupla que aparece más veces
en S que en R no aparece en la diferencia.

! Ejercicio 2.3.4: La selección también se puede realizar en bolsas. Proporcione una implementación
de MapReduce que produzca el número adecuado de copias de cada tupla t que pasa la
condición de selección. Es decir, producir pares clave-valor a partir de los cuales se pueda
obtener fácilmente el resultado correcto de la selección a partir de los valores.

Ejercicio 2.3.5: La operación del álgebra relacional R (A, B) ⊲⊳ B <C S (C, D)


produce todas las tuplas a B C D) tal que tupla a, b) está en relación R, la tupla CD) es
en S, y b <c. Dar una implementación MapReduce de esta operación, asumiendo
R y S son conjuntos.

! Ejercicio 2.3.6: En la Sección 2.3.5 afirmamos que la eliminación de duplicados es una


operación asociativa y conmutativa. Demuestre este hecho.

2.4 Extensiones de MapReduce


MapReduce demostró ser tan influyente que generó una serie de extensiones y
modificaciones. Estos sistemas suelen compartir una serie de características con los
sistemas MapReduce:

1. Están construidos sobre un sistema de archivos distribuido.

2. Administran un gran número de tareas que son instancias de un pequeño


número de funciones escritas por el usuario.

3. Incorporan un método para hacer frente a la mayoría de las fallas que ocurren
durante la ejecución de un trabajo grande, sin tener que reiniciar ese trabajo
desde el principio.

Comenzamos esta sección con una discusión de los sistemas de "flujo de trabajo", que
amplían MapReduce al admitir redes acíclicas de funciones, cada función implementada por una
colección de tareas. Si bien se han implementado muchos de estos sistemas (consulte las notas
bibliográficas de este capítulo), una opción cada vez más popular es Spark de UC Berkeley.
También está ganando importancia TensorFlow de Google. Este último, aunque generalmente
no se reconoce como un sistema de flujo de trabajo debido a su orientación muy específica a las
aplicaciones de aprendizaje automático, de hecho tiene una arquitectura de flujo de trabajo en el
fondo.
Otra familia de sistemas utiliza un modelo gráfico de datos. El cálculo ocurre en los
nodos del gráfico y los mensajes se envían desde cualquier nodo a cualquier nodo
adyacente. El sistema original de este tipo fue Pregel de Google, que tiene su propia forma
única de lidiar con las fallas. Pero ahora se ha vuelto común implementar una función de
modelo de gráfico sobre un sistema de flujo de trabajo y utilizar el sistema de archivos y la
función de gestión de fallas de este último.
42 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

2.4.1 Sistemas de flujo de trabajo

Sistemas de flujo de trabajo extienda MapReduce desde el flujo de trabajo simple de dos pasos
(la función Map alimenta la función Reducir) a cualquier colección de funciones, con un gráfico
acíclico que representa el flujo de trabajo entre las funciones. Es decir, hay un acíclico gráfico de
flujo cuyos arcos a → B representar el hecho de que la función a La salida es una entrada para
funcionar. B.
Los datos que se pasan de una función a la siguiente son un archivo de elementos de
un tipo. Si una función tiene una sola entrada, esa función se aplica a cada entrada de
forma independiente, al igual que las funciones Mapa y Reducir se aplican a sus elementos
de entrada individualmente. La salida de la función es un archivo recopilado del resultado
de aplicar la función a cada entrada. Si una función tiene entradas de más de un archivo,
los elementos de cada uno de los archivos se pueden combinar de varias formas. Pero la
función en sí se aplica a combinaciones de elementos de entrada, como máximo uno de
cada archivo de entrada. Veremos ejemplos de tales combinaciones cuando analicemos la
implementación de la unión y la unión relacional en la Sección 2.4.2.

F gramo

h I

Figura 2.6: Un ejemplo de un flujo de trabajo que es más complejo que la alimentación de mapas
Reducir

Ejemplo 2.6: En la figura 2.6 se muestra una sugerencia de cómo se vería un flujo de
trabajo. Allí, cinco funciones, F mediante j, pasar datos de izquierda a derecha de formas
específicas, por lo que el flujo de datos es acíclico y ninguna tarea necesita proporcionar
datos antes de que toda la entrada esté disponible. Por ejemplo, función h toma su
entrada de un archivo preexistente del sistema de archivos distribuidos. Cada uno de h Los
elementos de salida se pasan a las funciones. I y j, tiempo I toma las salidas de ambos F y h
como entradas. La salida de j se almacena en el sistema de archivos distribuidos o se pasa
a una aplicación que invocó este flujo de datos. ✷

De manera análoga a las funciones Map y Reduce, cada función de un flujo de trabajo puede ser
ejecutada por muchas tareas, a cada una de las cuales se le asigna una parte de la entrada a la función.
Un controlador maestro es responsable de dividir el trabajo entre las tareas que implementan una
función, posiblemente mediante el hash de los elementos de entrada para decidir la tarea adecuada
para recibir un elemento. Por lo tanto, al igual que las tareas de mapa, cada tarea que implementa una
función F tiene un archivo de salida de datos destinados a cada una de las tareas que implementan la
función o funciones sucesoras de F. Estos archivos se entregan
2.4. EXTENSIONES A MAPREDUCE 43

por el controlador maestro en el momento apropiado, después de que la tarea haya completado su
trabajo.
Las funciones de un flujo de trabajo, y por lo tanto las tareas, comparten con las tareas
de MapReduce una propiedad importante: la propiedad de bloqueo, en el sentido de que
solo entregan la salida después de que se completan. Como resultado, si una tarea falla,
no ha entregado salida a ninguno de sus sucesores en el gráfico de flujo. 7 Por lo tanto, un
controlador maestro puede reiniciar la tarea fallida en otro nodo de cálculo, sin
preocuparse de que la salida de la tarea reiniciada duplique la salida que anteriormente se
pasó a otra tarea.
Algunas aplicaciones de los sistemas de flujo de trabajo son efectivamente cascadas de
trabajos de MapReduce. Un ejemplo sería la unión de tres relaciones, donde un trabajo
MapReduce une las dos primeras relaciones y un segundo trabajo MapReduce une la
tercera relación con el resultado de unir las dos primeras relaciones. Ambos trabajos
usarían un algoritmo como el de la Sección 2.3.7.
Hay una ventaja en implementar tales cascadas como un solo flujo de trabajo. Por
ejemplo, el controlador maestro puede administrar el flujo de datos entre tareas y su
replicación, sin necesidad de almacenar el archivo temporal que es la salida de un trabajo
MapReduce en el sistema de archivos distribuidos. Al ubicar las tareas en los nodos de
cómputo que tienen una copia de su entrada, podemos evitar gran parte de la
comunicación que sería necesaria si almacenamos el resultado de un trabajo de
MapReduce y luego iniciamos un segundo trabajo de MapReduce (aunque Hadoop y otros
sistemas MapReduce también intentan para ubicar las tareas del mapa donde ya hay una
copia de su entrada).

2.4.2 Chispa
Spark es, en esencia, un sistema de flujo de trabajo. Sin embargo, es un avance sobre los primeros
sistemas de flujo de trabajo en varias formas, que incluyen:

1. Una forma más eficaz de afrontar los fracasos.

2. Una forma más eficiente de agrupar tareas entre nodos de cómputo y programar la
ejecución de funciones.

3. Integración de características del lenguaje de programación tales como bucle (que


técnicamente lo saca de la clase de sistemas de flujo de trabajo acíclico) y bibliotecas de
funciones.

La abstracción de datos central de Spark se llama Conjunto de datos distribuido


resistente, o RDD. Un RDD es un archivo de objetos de un tipo. El ejemplo principal de un
RDD que hemos visto hasta ahora son los archivos de pares clave-valor que se utilizan en
los sistemas MapReduce. También son los archivos que se pasan entre las funciones de las
que hablamos en relación con la figura 2.6. Los RDD se "distribuyen" en el sentido de que
un RDD normalmente se divide en trozos que pueden mantenerse en
7 Como discutiremos en la Sección 2.4.5, la propiedad de bloqueo solo es válida para los flujos de trabajo acíclicos, y

los sistemas que soportan la recursividad no pueden usarla para manejar fallas.
44 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

diferentes nodos de cálculo. Son "resilientes" en el sentido de que esperamos poder


recuperarnos de la pérdida de algunos o todos los fragmentos de un RDD. Sin embargo, a
diferencia de la abstracción de pares clave-valor de MapReduce, no existe ninguna restricción
sobre el tipo de elementos que componen un RDD.
Un programa Spark consta de una secuencia de pasos, cada uno de los cuales
normalmente aplica alguna función a un RDD para producir otro RDD. Tales operaciones
se llaman transformaciones. También es posible tomar datos del sistema de archivos
circundante, como HDFS, y convertirlos en un RDD, y tomar un RDD y devolverlo al sistema
de archivos circundante o producir un resultado que se devuelve a una aplicación que
llamado programa Spark. Los últimos tipos de operaciones se denominan
comportamiento.
No intentaremos enumerar todas las transformaciones y acciones disponibles que
están disponibles. Tampoco fijaremos los dictados de un lenguaje de programación en
particular, ya que las operaciones de Spark están diseñadas para ser expresadas en varios
lenguajes de programación diferentes. Sin embargo, estas son algunas de las operaciones
más utilizadas.

Mapa, mapa plano y filtro

La transformación de mapa toma un parámetro que es una función y aplica esa función a
cada elemento de un RDD, produciendo otro RDD. Esta operación debería recordarnos el
Mapa de MapReduce, pero no es exactamente lo mismo. En primer lugar, en MapReduce,
una función de mapa solo se puede aplicar a un par clave-valor. En segundo lugar, en
MapReduce, una función Map produce un conjunto de pares clave-valor, y cada par clave-
valor se considera un elemento independiente de la salida de la función Map. En Spark,
una función de mapa se puede aplicar a cualquier tipo de objeto, pero produce
exactamente un objeto como resultado. El tipo del objeto resultante puede ser un
conjunto, pero eso no es lo mismo que producir muchos objetos a partir de un objeto de
entrada. Si desea producir un conjunto de objetos a partir de un solo objeto, Spark le
proporciona otra transformación llamada Mapa plano, que es análogo a Map of
MapReduce, pero sin el requisito de que todos los tipos sean pares clave-valor.

Ejemplo 2.7: Suponga que nuestro RDD de entrada es un archivo de documentos, como en el
"recuento de palabras" del ejemplo 2.1. Podríamos escribir una función Spark Map que tome un
documento y produzca un conjunto de pares, con cada par del formulario ( w 1), donde
w es una de las palabras del documento. Sin embargo, si lo hacemos, entonces el RDD de
salida es una lista de conjuntos, cada conjunto consta de todas las palabras de un
documento, cada palabra emparejada con el entero 1. Si queremos duplicar la función
Map descrita en el Ejemplo 2.1, entonces necesitamos usar la transformación Flatmap de
Spark. Esa operación aplicada al RDD de documentos producirá otro RDD, cada uno de
cuyos elementos es un solo par ( w 1). ✷

Spark también proporciona una operación similar a una forma limitada de Map, llamada
Filtrar. En lugar de una función como parámetro, la transformación de filtro toma un
predicado que se aplica al tipo de objetos en el RDD de entrada. El predicado
2.4. EXTENSIONES A MAPREDUCE 45

devuelve verdadero o falso para cada objeto, y el RDD de salida de una transformación de
filtro consta solo de aquellos objetos en el RDD de entrada para los que la función de filtro
devuelve verdadero.

Ejemplo 2.8: Continuando con el ejemplo 2.7, suponga que queremos evitar contar las
palabras vacías: las palabras más comunes como "el" o "y". Podríamos escribir una función
de filtro que tenga incorporada la lista de palabras que queremos eliminar. Cuando se
aplica a un par ( w 1), esta función devuelve verdadero si y solo si w no está en la lista.
Luego podemos escribir un programa Spark que primero aplique Flatmap a
el RDD de documentos, produciendo un RDD R 1 que consta de un par w 1) por cada
aparición de la palabra w en cualquiera de los documentos. El programa entonces
aplica el filtro de eliminación de palabras vacías a R 1, producir otro RDD, R 2.
El último RDD consta de un par ( w 1) por cada aparición de palabra w en cualquier
de los documentos, pero solo si w no es una palabra de parada. ✷

Reducir

En Spark, la operación Reducir es una acción, no una transformación. Es decir,


la operación Reducir se aplica a un RDD pero devuelve un valor y no otro RDD.
Reducir toma un parámetro que es una función que toma dos elementos de algún
tipo particular T y devuelve otro elemento del mismo tipo T. Cuando se aplica a un
RDD cuyos elementos son de tipo T, Reducir se aplica repetidamente a cada par de
elementos consecutivos, reduciéndolos a un solo elemento. Cuando solo queda un
elemento, se convierte en el resultado de la operación Reducir.
Por ejemplo, si el parámetro es la función de suma, y esta instancia de Reducir
se aplica a un RDD cuyos elementos son números enteros, el resultado será un único
entero que es la suma de todos los números enteros en el RDD. Siempre que el
parámetro de función sea una función asociativa y conmutativa, como la suma, no
importa en qué orden se combinan los elementos del RDD de entrada. Sin embargo,
también es posible utilizar una función arbitraria, siempre que estemos satisfechos
con la combinación de elementos en cualquier orden.

Operaciones de bases de datos relacionales

Hay una serie de operaciones Spark integradas que se comportan como operadores de
álgebra relacional en relaciones que están representadas por RDD. Es decir, piense en los
elementos de los RDD como tuplas de una relación. La transformación Join toma dos RDD,
cada uno de los cuales representa una de las relaciones. El tipo de cada RDD debe ser un
par clave-valor y los tipos de clave de ambas relaciones deben ser iguales. La
transformación de unión luego busca dos objetos, uno de cada uno de sus RDD de
entrada, de modo que los valores clave sean los mismos, digamos ( k, x) y ( k, y). Para cada
par encontrado, Join produce el par clave-valor k, (x, y), y el RDD de salida consta de todos
esos objetos.
La operación group-by de SQL también se implementa en Spark mediante la
transformación GroupByKey. Esta transformación toma como entrada un RDD cuyo tipo
son pares clave-valor. El RDD de salida también es un conjunto de pares clave-valor con
46 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

el mismo tipo de clave. El tipo de valor para la salida es una lista de valores del tipo de
entrada. GroupByKey ordena su RDD de entrada por clave y para cada clave k produce
el par ( k, [v 1, v 2,. . . , v norte]) tal que el v I son todos los valores asociados con la clave k
en el RDD de entrada. Observe que GroupByKey es exactamente la operación que
MapReduce realiza entre bastidores para agrupar la salida de la función Map por
tecla.

2.4.3 Implementación de Spark


Hay varias formas en que la implementación de Spark difiere de Hadoop u otras
implementaciones de MapReduce. Discutiremos dos mejoras importantes: la
evaluación perezosa de los RDD y el linaje de los RDD. Antes de hacerlo, debemos
mencionar una forma en la que Spark es similar a MapReduce: la forma en que se
administran los RDD grandes.
Recuerde que al aplicar Map a un archivo grande, MapReduce divide ese archivo en
fragmentos y crea una tarea de Map para cada fragmento o grupo de fragmentos. Los
fragmentos y sus tareas se distribuyen normalmente entre muchos nodos informáticos
diferentes. Asimismo, muchas tareas de Reducir pueden ejecutarse en paralelo en diferentes
nodos de cómputo, y cada una de estas tareas toma una parte del conjunto completo de pares
clave-valor que se pasan de Mapa a Reducir. Spark también permite que cualquier RDD se divida
en trozos, a los que llama divisiones. Cada división se puede asignar a un nodo de cálculo
diferente, y la transformación en ese RDD se puede realizar en paralelo en cada una de las
divisiones.

Evaluación perezosa

Como se mencionó en la Sección 2.4.1, es común que los sistemas de flujo de trabajo
exploten la propiedad de bloqueo para el manejo de errores. Para hacerlo, se aplica una
función a un solo archivo intermedio (análogo a un RDD) y la salida de esa función se pone
a disposición de los consumidores de esa salida sólo después de que se completa la
función. Sin embargo, Spark no aplica transformaciones a los RDD hasta que sea
necesario, normalmente porque debe aplicar alguna acción, por ejemplo, almacenar un
RDD calculado en el sistema de archivos circundante o devolver un resultado a una
aplicación.
El beneficio de esta estrategia de evaluación perezosa es que muchos RDD no se
construyen todos a la vez. Cuando se crea una división de un RDD en un nodo, se puede
usar inmediatamente en el mismo nodo de cálculo para aplicar otra transformación. El
beneficio de esta estrategia es que este RDD nunca se almacena en el disco y nunca se
transmite a otros nodos de cómputo, ahorrando así órdenes de magnitud en el tiempo de
ejecución en algunos casos.

Ejemplo 2.9: Considere la situación sugerida en el ejemplo 2.8, donde Flat-


map se aplica a un RDD, al que nos referiremos como R 0. Tenga en cuenta que RDD R 0
se crea convirtiendo el archivo externo de documentos en un RDD. Como R 0 es un
archivo grande, desearemos dividirlo en divisiones y operar sobre las divisiones en
paralelo.
2.4. EXTENSIONES A MAPREDUCE 47

La primera transformación en R 0 aplica Flatmap para crear un conjunto de pares (


w 1) para cada palabra. Por cada división de R 0, una división del RDD resultante, que
llamamos R 1 en el ejemplo 2.8, se crea en el mismo nodo de cálculo. Esta división
de R 1 luego se pasa al filtro de transformación, que elimina los pares cuyo primer
componente es una palabra de parada. Cuando este filtro se aplica a la división, el
el resultado es una división del RDD R 2, ubicado en el mismo nodo de cálculo.
Sin embargo, ni el mapa plano ni las transformaciones de filtro se producen a menos que
la acción se aplica a R 2. Por ejemplo, el programa Spark puede almacenar R 2 en el sistema de
archivos circundante o realice una operación de reducción que cuente las ocurrencias
de las palabras. Solo cuando el programa llega a esta acción, Spark aplica la
Transformaciones de mapa plano y filtro para R 0, ejecutar estas transformaciones en cada uno de los
nodos de cómputo que contiene una división de R 0, en paralelo. Por lo tanto, las divisiones
de R 1 y R 2 existen sólo localmente en el nodo de cómputo que los creó, y a menos
que el programador exija explícitamente que se mantengan, estas divisiones
se eliminan tan pronto como se utilizan localmente. ✷

Resiliencia de los RDD

Naturalmente, uno puede preguntarse qué sucede en el ejemplo 2.9 si falla un nodo de cálculo
después de crear una división de R 1 y antes de transformar esa escisión en una escisión de
R 2. Ya que R 1 no está respaldado en el sistema de archivos, ¿no se pierde para siempre? El sustituto de
Spark para el almacenamiento redundante de valores intermedios es registrar el linaje
de cada RDD que crea. El linaje le dice al sistema Spark cómo recrear el RDD, o una
división del RDD, si es necesario.

Ejemplo 2.10: Considerando de nuevo la situación descrita en el ejemplo 2.9,


el linaje de R 2 diría que se crea aplicando a R 1 lo particular
Operación de filtro que elimina palabras vacías. Sucesivamente, R 1 se crea a partir de R 0 mediante la
operación de mapa plano que convierte las palabras de un documento en ( w 1) parejas. Y
R 0 fue creado a partir de un archivo particular del sistema de archivos circundante.
Por ejemplo, si perdemos una división de R 2, sabemos que podemos reconstruirlo a partir de
la división correspondiente de R 1. Pero dado que esa división existe en el mismo nodo de cálculo,
probablemente también la hemos perdido. Si es así, podríamos reconstruirlo a partir de
la división correspondiente de R 0, que probablemente también se pierda si este nodo de cálculo
ha fallado. Pero sabemos que podemos reconstruir la escisión de R 0 del sistema de
archivos circundante, que presumiblemente es redundante y no se perderá.
Por lo tanto, Spark encontrará otro nodo de cálculo, reconstruirá la división perdida de R 0
del sistema de archivos allí, y luego aplique las transformaciones conocidas necesarias
para reconstruir las divisiones correspondientes de R 1 y R 2. ✷

Como podemos ver en el Ejemplo 2.10, la recuperación de una falla de nodo puede ser más
compleja en Spark que en MapReduce o en sistemas de flujo de trabajo que almacenan valores
intermedios de manera redundante. Sin embargo, el intercambio de una recuperación más compleja
cuando las cosas van mal contra una mayor velocidad cuando las cosas van bien es generalmente
bueno. Cuanto más rápido se ejecuta un programa Spark, menos posibilidades hay de que falle un
nodo mientras se ejecuta.
48 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Debemos contrastar la necesidad de Spark de poder ejecutar un programa frente a fallas


con la necesidad de almacenamiento redundante de archivos que se espera que existan durante
un período prolongado. Durante un largo período, las fallas son casi seguras, por lo que es muy
probable que perdamos partes de un archivo si no lo almacenamos de manera redundante. Pero
en un período corto, minutos o incluso horas, existe una buena posibilidad de evitar fallas. Por
tanto, es razonable estar dispuesto a pagar más cuando es un fracaso en este caso.

2.4.4 TensorFlow
TensorFlow es un sistema de código abierto desarrollado inicialmente en Google para admitir
aplicaciones de aprendizaje automático. Al igual que Spark, TensorFlow proporciona una interfaz
de programación en la que se escribe una secuencia de pasos. Los programas suelen ser
acíclicos, aunque, como Spark, es posible iterar bloques de código.
Una diferencia importante entre Spark y TensorFlow es el tipo de datos que se
pasan entre los pasos del programa. En lugar del RDD, TensorFlow usa tensores; un
tensor es simplemente una matriz multidimensional.

Ejemplo 2.11: Una constante, por ejemplo, 3,14159, se considera un tensor de dimensión
cero. Un vector es un tensor unidimensional. Por ejemplo, el vector (1, 2, 3) se puede
escribir en tensorFlow como [1., 2., 3.]. Una matriz es un tensor bidimensional. Para
ejemplo, la matriz

1 2 3 4
5 6 7 8
9 10 11 12

se expresa como [[1., 2., 3., 4.], [5., 6., 7., 8.], [9., 10., 11., 12.]].
También son posibles matrices de mayor dimensión. Por ejemplo, un cubo de ceros de
2 por 2 por 2 se representa como [[[0., 0.], [0., 0.]], [[0., 0.], [0. , 0.]]]. ✷

Aunque los tensores son de hecho una forma restringida de RDD, el poder de
TensorFlow proviene de su selección de operaciones integradas. Las operaciones de
álgebra lineal están disponibles como funciones. Por ejemplo, si desea una matriz C ser el
producto de matrices A y B, puedes escribir

C = tensorflow.matmul (A, B)

Aún más poderosos son los enfoques comunes del aprendizaje automático que se integran
como operaciones. una sola declaración en el lenguaje TensorFlow puede hacer que un modelo
que es un tensor se construya a partir de datos de entrenamiento, que también se representa
como un tensor, usando un método como el descenso de gradiente. (Discutimos el descenso de
gradiente en las Secciones 9.4.5 y 12.3.4).
2.4. EXTENSIONES A MAPREDUCE 49

2.4.5 Extensiones recursivas de MapReduce


Muchos cálculos a gran escala son en realidad recursiones. Un ejemplo importante es
PageRank, que es el tema del Capítulo 5. Ese cálculo es, en términos simples, el
cálculo del punto fijo de una multiplicación matriz-vector. Se calcula en sistemas
MapReduce mediante la aplicación iterativa del algoritmo de multiplicación matriz-
vector descrito en la Sección 2.3.1, o mediante una estrategia más compleja que
presentaremos en la Sección 5.2. La iteración generalmente continúa por un número
desconocido de pasos, cada paso es un trabajo MapReduce, hasta que los resultados
de dos iteraciones consecutivas están lo suficientemente cerca como para creer que
se ha producido la convergencia. Un segundo ejemplo importante de un algoritmo
recursivo en datos masivos es el descenso de gradientes, que acabamos de
mencionar en relación con TensorFlow.
Las recurrencias presentan un problema para la recuperación de fallas. Las tareas recursivas
carecen inherentemente de la propiedad de bloqueo necesaria para el reinicio independiente de
las tareas fallidas. Es imposible que una colección de tareas recursivas entre sí, cada una de las
cuales tiene una salida que es entrada para al menos algunas de las otras tareas, produzca
salida solo al final de la tarea. Si todos siguieran esa política, ninguna tarea recibiría ningún
aporte y no se podría lograr nada. Como resultado, se debe implementar algún mecanismo que
no sea el simple reinicio de las tareas fallidas en un sistema que maneja flujos de trabajo
recursivos (gráficos de flujo que no son acíclicos). Comenzaremos estudiando un ejemplo de
recursividad implementada como un flujo de trabajo y luego discutiremos enfoques para lidiar
con fallas de tareas.

Ejemplo 2.12: Supongamos que tenemos una gráfica dirigida cuyos arcos están representados
por la relación E (X, Y), lo que significa que hay un arco desde el nodo X al nodo Y.
Deseamos calcular la relación de caminos P (X, Y), lo que significa que hay una ruta de
longitud 1 o más desde el nodo X al nodo Y. Es decir, PAG es el clausura transitiva
de MI. Un algoritmo recursivo simple para hacerlo es:

1. Empiece con P (X, Y) = E (X, Y).

2. Mientras cambia la relación PAG ocurrir, agregar a PAG todas las tuplas en

π X, Y P (X, Z) ⊲⊳ P (Z, Y)

Es decir, encontrar pares de nodos X y Y tal que para algún nodo Z se sabe que hay
un camino desde X para Z y también un camino conocido desde Z para Y.

La figura 2.7 sugiere cómo podríamos organizar tareas recursivas para realizar
este cálculo. Hay dos tipos de tareas: Unir tareas y Tareas duplicadas.
Existen norte Unir tareas, para algunos norte, y cada uno corresponde a un cubo de una función
hash h. Una tupla de ruta P (a, b), cuando se descubre, se convierte en entrada para dos tareas
de Join: las numeradas decir ah) y media pensión). El trabajo del I th Unirse a la tarea, cuando
recibe la tupla de entrada P (a, b), es encontrar algunas otras tuplas vistas anteriormente (y
almacenadas localmente por esa tarea).

1. Tienda P (a, b) en la zona.


50 CAPITULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Entrar Dup-elim
tarea tarea
0 0

Entrar Dup-elim Para unirse a la tarea h (c)

tarea tarea

1 1

.
.
.
.
.
.
P (c, d) si Dup-elim
g (c, d) = j tarea
P (c, d) si nunca
j
(a, b) si Entrar visto antes
(a) = yo o tarea
.
(b) = yo I
.
.
.
.
.

Para unirse a la tarea h (d)

Figura 2.7: Implementación del cierre transitivo mediante una colección de tareas
recursivas

2. Si h (a) = yo luego busca tuplas P (x, a) y producir una tupla de salida P (x, b).

3. Si h (b) = yo luego busca tuplas P (b, y) y producir una tupla de salida Pagar).

Tenga en cuenta que, en raras ocasiones, tenemos h (a) = h (b), por lo que se ejecutan tanto (2) como
(3). Pero generalmente, solo uno de estos debe ejecutarse para una tupla determinada.
Tambien hay metro Tareas de eliminación duplicada, y cada una corresponde a un
grupo de una función hash gramo eso requiere dos argumentos. Si P (c, d) es una salida de
alguna tarea Join, luego se envía a la tarea Dup-elim j = g (c, d). Al recibir esta tupla, el
j La tarea Dup-elim comprueba que no haya recibido esta tupla antes, ya que su trabajo es
la eliminación de duplicados. Si se recibió anteriormente, la tupla se ignora. Pero si esta
tupla es nueva, se almacena localmente y se envía a dos tareas Join, las numeradas
h (c) y h (d).
Cada tarea de unión tiene metro archivos de salida, uno para cada tarea Dup-elim, y
cada tarea Dup-elim tiene norte archivos de salida: uno para cada tarea Unir. Estos
archivos pueden distribuirse de acuerdo con varias estrategias. Inicialmente, el E (a, b) Las
tuplas que representan los arcos del gráfico se distribuyen a las tareas Dup-elim, con
E (a, b) siendo enviado como P (a, b) a la tarea Dup-Elim g (a, b). El controlador maestro
2.4. EXTENSIONES A MAPREDUCE 51

espera hasta que cada tarea Unir haya procesado toda su entrada para una ronda. Luego,
todos los archivos de salida se distribuyen a las tareas Dup-elim, que crean su propia
salida. Esa salida se distribuye a las tareas Unirse y se convierte en su entrada para la
siguiente ronda. ✷

En el ejemplo 2.12 no es esencial tener dos tipos de tareas. Más bien, las tareas de unión
podrían eliminar los duplicados a medida que se reciben, ya que de todos modos deben
almacenar sus entradas recibidas anteriormente. Sin embargo, esta disposición tiene una
ventaja cuando debemos recuperarnos de una tarea fallida. Si cada tarea almacena todos los
archivos de salida que ha creado, y colocamos las tareas de unión en diferentes racks de las
tareas Dup-elim, entonces podemos tratar con cualquier nodo de cálculo o falla de un solo rack.
Es decir, una tarea de unión que deba reiniciarse puede obtener todas las entradas generadas
previamente que necesita de las tareas de eliminación duplicada, y viceversa.

En el caso particular de calcular el cierre transitivo, no es necesario evitar que una


tarea reiniciada genere salidas que la tarea original generó previamente. En el cálculo
del cierre transitivo, el redescubrimiento de un camino no influye en la respuesta
final. Sin embargo, muchos cálculos no pueden tolerar una situación en la que tanto
la versión original como la reiniciada de una tarea pasan el mismo resultado a otra
tarea. Por ejemplo, si el paso final del cálculo fuera una agregación, digamos un
recuento del número de nodos alcanzados por cada nodo en el gráfico,
obtendríamos la respuesta incorrecta si contamos un camino dos veces.

Hay al menos tres enfoques diferentes que se han utilizado para tratar las fallas
durante la ejecución de un programa recursivo.

1. MapReduce iterado: Escriba la recursividad como ejecución repetida de un trabajo


MapReduce o de una secuencia de trabajos MapReduce. Luego, podemos confiar en
el mecanismo de falla de la implementación de MapReduce para manejar las fallas
en cualquier paso. El primer ejemplo de tal sistema fue HaLoop (véanse las notas
bibliográficas de este capítulo).

2. El enfoque de la chispa: El lenguaje Spark en realidad incluye declaraciones


iterativas, como bucles for que permiten la implementación de recursiones.
Aquí, la gestión de fallos se implementa utilizando los mecanismos de linaje y
evaluación diferida de Spark. Además, el programador Spark tiene opciones
para almacenar estados intermedios de la recursividad.

3. Sistemas masivos síncronos: Estos sistemas utilizan un modelo de cálculo basado en


gráficos que describiremos a continuación. Por lo general, utilizan otro enfoque de
resiliencia: puntos de control periódicos.

2.4.6 Sistemas masivos síncronos


Otro enfoque para implementar algoritmos recursivos en un clúster informático está
representado por el sistema Pregel de Google, que fue el primer ejemplo de un
52 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Sistema sincrónico masivo basado en gráficos para procesar cantidades masivas de datos.
Tal sistema ve sus datos como un gráfico. Cada nodo del gráfico corresponde
aproximadamente a una tarea (aunque en la práctica muchos nodos de un gráfico grande
se agruparían en una sola tarea, como en las tareas Unir del ejemplo 2.12). Cada nodo del
gráfico genera mensajes de salida que están destinados a otros nodos del gráfico, y cada
nodo del gráfico procesa las entradas que recibe de otros nodos.

Ejemplo 2.13: Suponga que nuestros datos son una colección de arcos ponderados de un gráfico
y queremos encontrar, para cada nodo del gráfico, la longitud del camino más corto a cada uno
de los otros nodos. A medida que se ejecuta el algoritmo, cada nodo a almacenará un conjunto
de pares b, w), dónde w es la longitud de la ruta más corta desde el nodo a al nodo B que se
conoce actualmente.
Inicialmente, cada nodo del gráfico a almacena el conjunto de pares ( b, w) tal
que hay un arco desde a para B de peso w. Estos hechos se envían a todos los demás
nodos, como triples ( a, b, w), con el significado pretendido de que el nodo a sabe de
un camino largo w al nodo B. 8 Cuando el nodo a recibe un triple c, d, w), debe decidir
si este hecho implica un camino más corto que a ya sabe de sí mismo al nodo D.
Nodo a busca su distancia actual a C; es decir, encuentra el par ( CV) almacenados
localmente, si hay uno. También encuentra el par ( d, u) si hay uno. Si w + v <u, luego
el par d, u) es reemplazado por ( d, w + v), y si no hubiera pareja d, u), luego el par d,
w + v) se almacena en el nodo una. Además, a los otros nodos se les envía el mensaje (
a, d, w + v) en cualquiera de estos dos casos. ✷

Los cálculos en Pregel se organizan en superpasos. En un superpaso, se procesan


todos los mensajes que fueron recibidos por cualquiera de los nodos en el superpaso
anterior (o inicialmente, si es el primer superpaso), y luego todos los mensajes
generados por esos nodos se envían a su destino. Es este empaquetado de muchos
mensajes en uno lo que le da a este enfoque el nombre de "sincrónico masivo".
Hay una ventaja muy importante de agrupar mensajes de esta manera. La
comunicación a través de una red generalmente requiere una gran cantidad de gastos
generales para enviar cualquier mensaje, por breve que sea. Suponga que en el ejemplo
2.13 enviamos un solo hecho nuevo de la distancia más corta al nodo relevante cada vez
que se descubre uno. La cantidad de mensajes enviados sería enorme si el gráfico fuera
grande y no sería realista implementar tal algoritmo. Sin embargo, en un sistema
sincrónico masivo, una tarea que tiene la responsabilidad de administrar muchos nodos
del gráfico puede agrupar todos los mensajes que envían sus nodos a cualquiera de los
nodos que está administrando otra tarea. Por lo general, esa elección ahorra órdenes de
magnitud en el tiempo necesario para enviar todos los mensajes necesarios.

Gestión de fallos en Pregel

En caso de una falla en el nodo de cómputo, no se intenta reiniciar las tareas fallidas en
ese nodo de cómputo. Más bien, Pregel puestos de control todo su cálculo después
8 Este algoritmo usa demasiada comunicación, pero servirá como un ejemplo simple del modelo de cálculo
de Pregel.
2.5. EL MODELO DE COSTOS DE COMUNICACIÓN 53

algunos de los superpasos. Un punto de control consiste en realizar una copia del estado
completo de cada tarea, para que se pueda reiniciar desde ese punto si es necesario. Si falla
algún nodo de cálculo, todo el trabajo se reinicia desde el punto de control más reciente.
Aunque esta estrategia de recuperación provoca muchas tareas que no han dejado de
rehacer su trabajo, resulta satisfactoria en muchas situaciones. Recuerde que la razón por
la que los sistemas MapReduce admiten el reinicio solo de las tareas fallidas es que
queremos tener la seguridad de que el tiempo esperado para completar todo el trabajo
ante fallas no es mucho mayor que el tiempo para ejecutar el trabajo sin fallas. Cualquier
sistema de gestión de fallas tendrá esa propiedad siempre que el tiempo para recuperarse
de una falla sea mucho menor que el tiempo promedio entre fallas. Por lo tanto, solo es
necesario que Pregel controle su cálculo después de una serie de superpasos de modo
que la probabilidad de falla durante esa cantidad de superpasos sea baja.

2.4.7 Ejercicios para la sección 2.4


! Ejercicio 2.4.1: Suponga que un trabajo consta de norte tareas, cada una de las cuales lleva tiempo t
segundos. Por lo tanto, si no hay fallas, la suma de todos los nodos de cálculo del tiempo
necesario para ejecutar tareas en ese nodo es Nuevo Testamento. Suponga también que la
probabilidad de que falle una tarea es pag por trabajo por segundo, y cuando una tarea falla, la
sobrecarga de administración del reinicio es tal que agrega 10 t segundos al tiempo total de
ejecución del trabajo. ¿Cuál es el tiempo total de ejecución esperado del trabajo?

! Ejercicio 2.4.2: Suponga que un trabajo de Pregel tiene una probabilidad pag de una falla durante
cualquier superpaso. Suponga también que el tiempo de ejecución (sumado en todos los nodos de
cálculo) de tomar un punto de control es C multiplicado por el tiempo que se tarda en ejecutar un
superpaso. Para minimizar el tiempo de ejecución esperado del trabajo, ¿cuántos superpasos
deberían transcurrir entre los puestos de control?

2.5 El modelo de costos de comunicación


En esto sección presentaremos un modelo para medir la calidad de los algoritmos
implementado en un clúster de computación del tipo discutido hasta ahora en este
capítulo. Suponemos que el cálculo se describe mediante un flujo de trabajo acíclico, como
se analiza en la sección 2.4.1. Para muchas aplicaciones, el cuello de botella es mover datos
entre tareas, como transportar los resultados de las tareas de Mapa a sus tareas de
Reducir adecuadas. Como ejemplo, exploramos el cálculo de uniones de múltiples vías
como trabajos únicos de MapReduce, y vemos que en algunas situaciones, este enfoque es
más eficiente que la sencilla cascada de uniones de dos vías.

2.5.1 Costo de comunicación para redes de tareas


Imagine que un algoritmo se implementa mediante una red acíclica de tareas. Estas tareas
pueden ser tareas de Map que alimentan tareas de Reducir, como en un algoritmo estándar de
MapReduce, o pueden ser varios trabajos de MapReduce en cascada, o de forma más general.
54 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

estructura del flujo de trabajo, como una colección de tareas, cada una de las cuales implementa
el flujo de trabajo de la figura 2.6. 9 los costo de comunicación de una tarea es el tamaño de la
entrada a la tarea. Este tamaño se puede medir en bytes. Sin embargo, dado que usaremos
operaciones de bases de datos relacionales como ejemplos, a menudo usaremos el número de
tuplas como medida de tamaño.
los costo de comunicación de un algoritmo es la suma del costo de comunicación de
todas las tareas que implementan ese algoritmo. Nos centraremos en el coste de la
comunicación como forma de medir la eficiencia de un algoritmo. En particular, no
consideramos la cantidad de tiempo que tarda cada tarea en ejecutarse al estimar el
tiempo de ejecución de un algoritmo. Si bien hay excepciones, en las que predomina el
tiempo de ejecución de las tareas, estas excepciones son raras en la práctica. Podemos
explicar y justificar la importancia del costo de la comunicación de la siguiente manera.

• El algoritmo ejecutado por cada tarea tiende a ser muy simple, a menudo lineal en
el tamaño de su entrada.

• La velocidad de interconexión típica de un clúster informático es de un gigabit por


segundo. Puede parecer mucho, pero es lento en comparación con la velocidad a la
que un procesador ejecuta las instrucciones. Además, en muchas arquitecturas de
clúster, existe competencia por la interconexión cuando varios nodos de cómputo
necesitan comunicarse al mismo tiempo. Como resultado, el nodo de cálculo puede
hacer mucho trabajo en un elemento de entrada recibido en el tiempo que lleva
entregar ese elemento.

• Incluso si una tarea se ejecuta en un nodo de cálculo que tiene una copia de los fragmentos en
los que opera la tarea, ese fragmento normalmente se almacenará en el disco y el tiempo
necesario para mover los datos a la memoria principal puede exceder el tiempo necesario. para
operar con los datos una vez que estén disponibles en la memoria.

Suponiendo que el costo de comunicación es el costo dominante, aún podríamos preguntarnos por
qué contamos solo el tamaño de entrada y no el tamaño de salida. La respuesta a esta pregunta
involucra dos puntos:

1. Si el resultado de una tarea τ es entrada a otra tarea, entonces el tamaño de τ La


salida se tendrá en cuenta al medir el tamaño de entrada para la tarea de recepción.
Por lo tanto, no hay razón para contar el tamaño de ninguna salida, excepto para
aquellas tareas cuya salida forma el resultado de todo el algoritmo.

2. Pero en la práctica, la salida del algoritmo rara vez es grande en comparación


con la entrada o los datos intermedios producidos por el algoritmo. La razón es
que los productos masivos no se pueden utilizar a menos que se resuman o
agreguen de alguna manera. Por ejemplo, aunque en el ejemplo 2.12
hablamos de calcular el cierre transitivo completo de un gráfico, en la práctica
querríamos algo mucho más simple, como el recuento del número de nodos.
9 Recuerde que esta figura representa funciones, no tareas. Como red de tareas, habría, por ejemplo,
muchas tareas que implementan funciones F, cada uno de los cuales alimenta datos a cada una de las tareas
para la función gramo y cada una de las tareas para la función I.
2.5. EL MODELO DE COSTOS DE COMUNICACIÓN 55

accesible desde cada nodo, o el conjunto de nodos accesibles desde un solo


nodo.

Ejemplo 2.14: Evaluemos el costo de comunicación para el algoritmo de unión de la


Sección 2.3.7. Supongamos que nos unimos R (A, B) ⊲⊳ S (B, C), y los tamaños de las
relaciones R y S están r y s, respectivamente. Cada trozo de archivos que contiene
R y S se alimenta a una tarea de mapa, por lo que la suma de los costos de comunicación para
todas las tareas de mapa es r + s. Tenga en cuenta que en una ejecución típica, cada una de las
tareas de mapa se ejecutará en un nodo de cálculo que contiene una copia del fragmento al que
se aplica. Por lo tanto, no se necesita comunicación entre los entrenudos para las tareas de
Mapa, pero aún deben leer sus datos desde el disco. Dado que todo lo que hacen las tareas de
Mapa es realizar una transformación simple de cada tupla de entrada en un par clave-valor,
esperamos que el costo de cálculo sea pequeño en comparación con el costo de comunicación,
independientemente de si la entrada es local para la tarea o debe ser transportado a su nodo de
cálculo.
La suma de los resultados de las tareas del mapa es aproximadamente tan grande como sus
entradas. Cada par clave-valor de salida se envía exactamente a una tarea de Reducir y es poco
probable que esta tarea de Reducir se ejecute en el mismo nodo de cálculo. Por lo tanto, es
probable que la comunicación de las tareas de mapa a las tareas de reducción se realice a través
de la interconexión del clúster, en lugar de la memoria al disco. Esta comunicacion es O (r + s),
por lo que el costo de comunicación del algoritmo de unión es O (r + s).
Las tareas Reducir ejecutan el reductor (aplicación de la función Reducir a una
tecla y su lista de valores asociada) para uno o más valores de atributo B.
Cada reductor toma las entradas que recibe y las divide entre tuplas que provienen
de R y los que vinieron de S. Cada tupla de R se empareja con cada tupla de S para
producir una salida. El tamaño de salida de la unión puede ser mayor o menor que r
+ s, dependiendo de la probabilidad de que un determinado R- tupla se une con un
dado S- tupla. Por ejemplo, si hay muchos diferentes B- valores, esperaríamos que la
salida sea pequeña, mientras que si hay pocos B- valores, es probable una gran salida.

Si la salida es grande, entonces el costo de cálculo de generar todas las salidas de un


reductor podría ser mucho mayor que O (r + s). Sin embargo, nos basaremos en nuestra
suposición de que si la salida de la unión es grande, entonces probablemente se esté
realizando alguna agregación para reducir el tamaño de la salida. Será necesario
comunicar el resultado de la combinación a otra colección de tareas que realicen esta
agregación y, por lo tanto, el costo de comunicación será al menos proporcional al cálculo
necesario para producir la salida de la combinación. ✷

2.5.2 Hora del reloj de pared


Si bien el costo de la comunicación a menudo influye en nuestra elección de algoritmo para usar en un
entorno de computación en clúster, también debemos ser conscientes de la importancia de
hora del reloj de pared, el tiempo que tarda un algoritmo paralelo en finalizar. Usando un
razonamiento descuidado, se podría minimizar el costo total de comunicación asignando todo el
trabajo a una tarea y, por lo tanto, minimizar la comunicación total. sin embargo, el
56 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

El tiempo de reloj de pared de tal algoritmo sería bastante alto. Los algoritmos que sugerimos, o que
hemos sugerido hasta ahora, tienen la propiedad de que el trabajo se divide equitativamente entre las
tareas. Por lo tanto, el tiempo del reloj de pared sería aproximadamente tan pequeño como podría ser,
dado el número de nodos de cálculo disponibles.

2.5.3 Uniones de múltiples vías

Para ver cómo el análisis del costo de la comunicación puede ayudarnos a elegir un algoritmo en el
entorno de computación en clúster, examinaremos cuidadosamente el caso de una combinación de
múltiples vías. Existe una teoría general en la que nosotros:

1. Seleccione ciertos atributos de las relaciones involucradas en la unión natural de tres o


más relaciones para que sus valores tengan un hash, cada uno en un cierto número de
cubos.

2. Seleccione el número de depósitos para cada uno de estos atributos, sujeto a la


restricción de que el producto de los números de depósitos para cada atributo es k,
el número de reductores que se utilizarán.

3. Identifique cada uno de los k reductores con un vector de números de cubo. Estos vectores
tienen un componente para cada uno de los atributos seleccionados en el paso (1).

4. Envíe tuplas de cada relación a todos aquellos reductores donde pueda encontrar tuplas
con las que unirse. Es decir, la tupla dada t tendrá valores para algunos de los atributos
seleccionados en el paso (1), por lo que podemos aplicar la función o funciones hash a
esos valores para determinar ciertos componentes del vector que identifica a los
reductores. Se desconocen otros componentes del vector, por lo que t debe enviarse a los
reductores para todos los vectores que tengan algún valor en estos componentes
desconocidos.

Algunos ejemplos de esta técnica general aparecen en los ejercicios. Aquí, solo
veremos la unión R (A, B) ⊲⊳ S (B, C) ⊲⊳ T (C, D) como ejemplo. Supongamos que las
relaciones R, S, y T tener tamaños r, s, y t, respectivamente, y por simplicidad,
supongamos pag es la probabilidad de que

1. An R- tupla y y S- tupla de acuerdo B, y también la probabilidad de que

2. An S- tupla y una T - tupla de acuerdo C.

Si nos unimos R y S Primero, usando el algoritmo MapReduce de la Sección 2.3.7,


entonces el costo de comunicación es O (r + s), y el tamaño de la unión intermedia
R ⊲⊳ S es prs. Cuando unimos este resultado con T, la comunicación de este segundo
trabajo MapReduce es O (t + prs). Por lo tanto, el costo total de comunicación del algoritmo
que consta de dos uniones bidireccionales es O (r + s + t + prs). Si en cambio nos unimos S
y T primero, y luego únete R con el resultado, obtenemos otro algoritmo cuyo costo de
comunicación es O (r + s + t + pst).
Una tercera forma de realizar esta unión es utilizar un solo trabajo MapReduce que
une las tres relaciones a la vez. Supongamos que planeamos usar k reductores para esto
2.5. EL MODELO DE COSTOS DE COMUNICACIÓN 57

trabajo. Elegir números B y C que representa el número de cubos en los que haremos
hash B- y C- valores, respectivamente. Dejar h ser una función hash que envía
B- valores en B cubos y dejar gramo ser otra función hash que envíe C- valores en C
cubos. Requerimos que bc = k; es decir, cada reductor corresponde a un par de
cubos, uno para el B- valor y uno para el C- valor. El reductor correspondiente al par
de cangilones ( yo, j) es responsable de unir las tuplas R (u, v), S (v, w), y T (ancho, x)
cuando sea h (v) = yo y g (w) = j.
Como resultado, las tareas del mapa que envían tuplas de R, S, y T a los
reductores que los necesitan deben enviar R- y T - tuplas a más de un reductor. Por un
S- tupla S (v, w), conocemos el B- y C- valores, por lo que podemos enviar esta tupla solo al
reductor para h (v), g (w). Sin embargo, considere una R- tupla R (u, v). Sabemos
solo necesita ir a reductores que correspondan a h (v), y, para algunos y. Pero no sabemos
y; El valor de C podría ser cualquier cosa que sepamos. Por lo tanto, debemos enviar R (u,
v) para C reductores, ya que y podría ser cualquiera de los C cubos para
C- valores. Del mismo modo, debemos enviar el T - tupla T (ancho, x) a cada uno de los reductores
z, g (w) para cualquier z. Existen B tales reductores.

g (TC) = 1

g (C) = h (SB) = 2 y g (SC) = 1


0 1 2 3

1
h (B) =
2
h (RB) = 2
3

Figura 2.8: Dieciséis reductores juntos realizan una unión de 3 vías

Ejemplo 2.15: Suponer que b = c = 4, entonces k = 16. Se puede pensar que los
dieciséis reductores están dispuestos en un rectángulo, como sugiere la figura 2.8.
Allí, vemos un hipotético S- tupla S (v, w) para cual h (v) = 2 y g (w) = 1. Esta tupla es
enviada por su tarea Mapa solo al reductor para la clave (2, 1). También vemos un R-
tupla R (u, v). Ya que h (v) = 2, esta tupla se envía a todos los reductores (2, y), por
y = 1, 2, 3, 4. Finalmente, vemos un T - tupla T (ancho, x). Ya que g (w) = 1, esta tupla se
envía a todos los reductores ( z, 1) para z = 1, 2, 3, 4. Observe que estas tres tuplas se unen
y se encuentran exactamente en un reductor, el reductor de la tecla (2, 1). ✷

Ahora, suponga que los tamaños de R, S, y T son diferentes; recuerda que usamos r,
s, y t, respectivamente, para esos tamaños. Si hacemos hash B- valores a B cubos y
58 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Costo de cálculo de la unión de 3 vías

Cada uno de los reductores debe calcular la unión de partes de las tres relaciones, y es
razonable preguntarse si esta unión se puede tomar en un tiempo lo más pequeño
posible: lineal en la suma de los tamaños de la entrada y la salida para ese Reducir la
tarea. Si bien es posible que las combinaciones más complejas no se puedan calcular en
tiempo lineal, la combinación de nuestro ejemplo en ejecución se puede ejecutar en cada
proceso de Reducir de manera eficiente. Primero, cree un índice en RB, para organizar el R-
tuplas recibidas. Del mismo modo, cree un índice en TC Para el T - tuplas. Luego,
considere cada uno recibido S- tupla S (v, w). Utilice el índice en RB para encontrar todo R-
tuplas con RB = v y usa el índice en TC para encontrar todo
T - tuplas con TC = w.

C- valores a C cubos, donde bc = k, entonces el costo total de comunicación para


mover las tuplas a los reductores adecuados es la suma de:

1. s para enviar cada tupla S (v, w) al reductor h (v), g (w).

2. cr para enviar cada tupla R (u, v) al C reductores h (v), y para cada uno de los C
posibles valores de y.

3. bt para enviar cada tupla T (ancho, x) al B reductores z, g (w) para cada uno de los B
posibles valores de z.

También hay un costo r + s + t para hacer que cada tupla de cada relación se ingrese en una de
las tareas del Mapa. Este costo es fijo, independiente de antes de Cristo, y k.
Debemos seleccionar B y C, sujeto a la restricción bc = k, minimizar
s + cr + bt. Usaremos la técnica de los multiplicadores de Lagrange para encontrar el
lugar donde la función s + cr + bt - λ (antes de Cristo - k) tiene sus derivados con
respecto a B y C igual a 0. Es decir, debemos resolver las ecuaciones r - λb = 0 y
t - λc = 0. Desde r = λb y t = λc, podemos multiplicar los correspondientes s pagides de
estas ecuaciones para obtener rt = λ 2 antes de Cristo. Ya que bc = k, obtenemos rt = λ 2 k, o λ = pag rt / k.

Por lo tanto, la mínima


pag um costo de comunicación se obtiene cuando c = t / λ = kt / r,
y b = r / λ = kr / t.

Si sustituimos estos valores en la fórmula s + cr + bt, obtenemos s + 2 krt.
Ese es el costo de comunicación para las tareas de Reducir, a lo que debemos sumar
el costo s + r + t para la comunicacion √ n costo de las tareas del Mapa. El total
el costo de comunicación es por lo tanto r + 2 s + t + 2 √ krt. En la mayoría de las circunstancias, √ pueden
negligencia r + t, porque será menos de 2 krt, generalmente por un factor de OK).

Ejemplo 2.16: Veamos en qué circunstancias la combinación de 3 vías tiene un costo


de comunicación menor que la cascada de dos combinaciones de 2 vías. Para
simplificar las cosas, supongamos que R, S, y T son todos la misma relación R, que
representa la relación de “amigos” en una red social como Facebook. Existen
2.5. EL MODELO DE COSTOS DE COMUNICACIÓN 59

aproximadamente mil millones de suscriptores en Facebook, con un promedio de 300 amigos cada uno,
por lo que la relación R tiene r = 3 × 10 11 tuplas. Supongamos que queremos calcular R ⊲⊳ R ⊲⊳ R,
quizás como parte de un cálculo para encontrar el número de amigos o amigos de
amigos que tiene cada suscriptor, o quizás solo la persona con el mayor número
de amigos de amigos o √ f amigos. 10 El costo de comunicación de la combinación de 3 vías √ de R
consigo mismo es 4 r + 2 rk; 3 r representa el costo de las tareas del Mapa, y r + 2 kr 2
es el costo de la Re √ duce tareas. Dado que asumimos r = 3 × 10 11, este costo es
1.2 × 10 12 + 6 × 10 11 k.
Ahora considere el costo de comunicación de unirse R consigo mismo, y luego
uniendo el resultado con R de nuevo. Las tareas Mapa y Reducir para la primera se unen a cada
tiene un costo de 2 r, por lo que la primera unión solo tiene un costo de comunicación 4 r = 1.2 × 10 12.
Pero el tamaño de R ⊲⊳ R es largo. No podemos decir exactamente qué tan grande, ya que
los amigos tienden a caer en pandillas y, por lo tanto, una persona con 300 amigos tendrá
muchos menos que el número máximo posible de amigos de amigos, que es 90.000.
Estimemos de forma conservadora que el tamaño de R ⊲⊳ R no es 300 r, pero solo 30 r, o 9
× 10 12. El costo de comunicación para la segunda unión de ( R ⊲⊳ R) ⊲⊳ R
es entonces 1.8 × 10 13 + 6 × 10 11. Por tanto, el coste total de las dos combinaciones es
1.2 × 10 12 + 1.8 × 10 13 + 6 × 10 11 = 1,98 × 10 13.
Debemos preguntarnos si el costo de la combinación de 3 vías, que es

1.2 × 10 12 + 6 × 10 11 k

Is√menor que 1,98 × 10 13. Eso es así, siempre que 6 × 10 11 k < 1,86 × 10 13, o
k < 31. Es decir, la combinación de 3 vías será preferible siempre que no usemos más
de 31 2 = 961 reductores. ✷

2.5.4 Ejercicios para la sección 2.5


Ejercicio 2.5.1: ¿Cuál es el costo de comunicación de cada uno de los siguientes
algoritmos, en función del tamaño de las relaciones, matrices o vectores a los que se
aplican?

(a) El algoritmo de multiplicación matriz-vector de la Sección 2.3.2.

(b) El algoritmo de unión de la Sección 2.3.6.

(c) El algoritmo de agregación de la Sección 2.3.8.

(d) El algoritmo de multiplicación de matrices de la Sección 2.3.10.

! Ejercicio 2.5.2: Supongamos relaciones R, S, y T tener tamaños r, s, y t, respectivamente, y


queremos tomar la combinación de 3 vías R (A, B) ⊲⊳ S (B, C) ⊲⊳ T (A, C),
utilizando k reductores. Haremos hash de los valores de los atributos. A, B, y C para a, b, y C
cubos, respectivamente, donde abc = k. Cada reductor está asociado con un vector
10 Esta persona, o más en general, las personas con grandes círculos de amigos, son buenas personas para
iniciar una campaña de marketing dándoles muestras gratuitas.
60 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Star se une

Una estructura común para la minería de datos de datos comerciales es la estrella unirse.
Por ejemplo, una cadena de tiendas como Walmart mantiene una tabla de hechos cuyo tu-
Cada uno de los ples representa una sola venta. Esta relación parece FA 1, A 2,. . .),
donde cada atributo A I es una clave que representa uno de los componentes
importantes de la venta, como el comprador, el artículo comprado, la tienda
rama o la fecha. Para cada atributo clave hay un tabla de dimensiones
dando información sobre el participante. Por ejemplo, la dimensión ta-
ble D (A 1, B 11, B 12,. . .) podría representar compradores. A 1 es el comprador
ID, la clave de esta relación. los B 1 I Es posible que proporcione el nombre, la dirección, el
teléfono, etc. del comprador. Normalmente, la tabla de hechos es mucho más grande que
las tablas de dimensiones. Por ejemplo, podría haber una tabla de hechos de mil millones de
tuplas y diez tablas de dimensiones de un millón de tuplas cada una.
Los analistas extraen estos datos preguntando consultas analíticas que
normalmente unen la tabla de hechos con varias de las tablas de dimensiones (una "unión
en estrella") y luego agregan el resultado en una forma útil. Por ejemplo, un analista
podría preguntar "dame una tabla de ventas de pantalones, desglosada por región y color,
para cada mes de 2016". Bajo el modelo de costos de comunicación de esta sección, es
casi seguro que unir la tabla de hechos y las tablas de dimensiones mediante una
combinación de múltiples vías será más eficiente que unir las relaciones en pares. De
hecho, puede tener sentido almacenar la tabla de hechos sobre la cantidad de nodos de
cálculo disponibles, y replicar las tablas de dimensiones de forma permanente
exactamente de la misma manera en que las replicaríamos si tomáramos la combinación
de la tabla de hechos y todas las tablas de dimensiones. . En este caso especial, solo los
atributos clave (el A 's arriba) se han convertido en cubos, y el número de cubos para cada
atributo clave es proporcional al tamaño de su tabla de dimensiones.

de cubos, uno para cada una de las tres funciones hash. Encuentre, en función de r, s,
t, y k, los valores de a, b, y C que minimizan el costo de comunicación del algoritmo.

! Ejercicio 2.5.3: Supongamos que tomamos una combinación en estrella de una tabla de hechos FA 1, A 2,. . . , A metro)

con tablas de dimensiones D I( A I, B I) por yo = 1, 2,. . . , metro. Dejalo ser k reductores, cada
uno asociado con un vector de cubos, uno para cada uno de los atributos clave
A 1, A 2,. . . , A metro. Supongamos la cantidad de cubos en los que hacemos hash A I es a I.
Naturalmente, a 1 a 2 · · · a m = k. Finalmente, suponga que cada tabla de dimensiones D I tiene tamaño
D I, y el tamaño de la tabla de hechos es mucho mayor que cualquiera de estos tamaños. Encontrar
los valores de la a I que minimizan el costo de tomar la unión en estrella como una
operación de MapReduce.
2.6. TEORÍA DE LA COMPLEJIDAD PARA MAPREDUCE 61

2.6 Teoría de la complejidad para MapReduce


Ahora, exploraremos el diseño de algoritmos MapReduce con más detalle. La Sección 2.5
introdujo la idea de que la comunicación entre las tareas de Map y Reduce es a menudo el
cuello de botella cuando se realiza un cálculo de MapReduce. Aquí, veremos cómo el costo
de comunicación se relaciona con otros desiderata para los algoritmos de MapReduce, en
particular nuestro deseo de reducir el tiempo del reloj de pared y ejecutar cada reductor
en la memoria principal. Recuerde que un “reductor” es la ejecución de la función Reducir
en una sola tecla y su lista de valores asociada. El punto de la exploración en esta sección
es que para muchos problemas existe un espectro de algoritmos MapReduce que
requieren diferentes cantidades de comunicación. Además, cuanta menos comunicación
use un algoritmo, peor puede ser
en otra respeta, incluida la hora del reloj de pared y la cantidad de memoria principal
requiere .

2.6.1 Tamaño del reductor y tasa de replicación


Introduzcamos ahora los dos parámetros que caracterizan a las familias de
algoritmos MapReduce. El primero es el tamaño del reductor, que denotamos por q.
Este parámetro es el límite superior del número de valores que pueden aparecer en
la lista asociada con una sola clave. El tamaño del reductor se puede seleccionar con
al menos dos objetivos en mente.

1. Al hacer que el tamaño del reductor sea pequeño, podemos forzar que haya muchos reductores,
es decir, muchas claves diferentes según las cuales la entrada del problema se
divide por las tareas del mapa. Si también creamos muchas tareas de Reducir,
incluso una para cada reductor, habrá un alto grado de paralelismo y podemos
esperar un tiempo de reloj de pared bajo.

2. Podemos elegir un tamaño de reductor lo suficientemente pequeño como para estar


seguros de que el cálculo asociado con un solo reductor se puede ejecutar por completo
en la memoria principal del nodo de cálculo donde se encuentra su tarea Reducir.
Independientemente del cálculo realizado por los reductores, el tiempo de ejecución se
reducirá considerablemente si podemos evitar tener que mover datos repetidamente
entre la memoria principal y el disco.

El segundo parámetro es el tasa de replicación, denotado r. Nosotros de fi nimos r


para ser el número de pares clave-valor producidos por todas las tareas de Mapa en todas
las entradas, dividido por el número de entradas. Es decir, la tasa de replicación es la
comunicación promedio de las tareas de mapa a las tareas de reducción (medida contando
pares clave-valor) por entrada.

Ejemplo 2.17: Consideremos el algoritmo de multiplicación de matrices de una pasada de


la Sección 2.3.10. Suponga que todas las matrices involucradas son norte × norte matrices.
Entonces la tasa de replicación r es igual a norte. Ese hecho es fácil de ver, ya que para
cada elemento metro ij, existen norte pares clave-valor producidos; estos tienen todas las claves de
62 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

la forma ( yo, k), para 1 ≤ k ≤ norte. Asimismo, para cada elemento de la otra matriz,
decir norte jk, nosotros producimos norte pares clave-valor, cada uno con una de las claves ( yo,
k), para 1 ≤ I ≤ norte. En este caso, no solo es norte el número medio de pares clave-valor
producido para un elemento de entrada, pero cada entrada produce exactamente este número de
pares.
También vemos que q, el tamaño del reductor requerido es 2 norte. Es decir, para cada clave
( yo, k), existen norte pares clave-valor que representan elementos metro ij de la primera matriz
y otro norte pares clave-valor derivados de los elementos norte jk de la segunda
matriz. Si bien este par de valores representa solo un algoritmo particular para
multiplicación de matrices de un paso, veremos que es parte de un espectro de
algoritmos, y de hecho representa un punto extremo, donde q es tan pequeño como
puede ser, y r está en su máximo. De manera más general, existe un tradeo ff entre r y
q, que se puede expresar como qr ≥ 2 norte 2. ✷

2.6.2 Un ejemplo: combinaciones de similitud

Para ver el tradeo ff entre r y q en una situación realista, examinaremos un problema


conocido como unión de similitud. En este problema, se nos da un gran conjunto de
elementos. X y una medida de similitud s (x, y) que dice cuán similares son dos elementos
X y y de conjunto X están. En el capítulo 3 aprenderemos sobre las nociones más
importantes de similitud y también aprenderemos algunos trucos que nos permitirán
encontrar pares similares rápidamente. Pero aquí, consideraremos solo la forma bruta del
problema, donde tenemos que mirar cada par de elementos de X y determinar su similitud
aplicando la función s. Asumimos que s es simétrico, entonces s (x, y) = s (y, x),
pero no asumimos nada más sobre s. La salida del algoritmo son aquellos pares cuya
similitud excede un umbral dado t.
Por ejemplo, supongamos que tenemos una colección de un millón de imágenes, cada una de un
tamaño de un megabyte. Por lo tanto, el conjunto de datos tiene un tamaño de un terabyte. No
intentaremos describir la función de similitud s, pero podría, por ejemplo, implicar dar valores más
altos cuando las imágenes tienen aproximadamente la misma distribución de colores o cuando las
imágenes tienen regiones correspondientes con la misma distribución de colores. El objetivo sería
descubrir pares de imágenes que muestren el mismo tipo de objeto o escena. Este problema es
extremadamente difícil, pero la clasificación por distribución de color suele ser de alguna ayuda para
lograr ese objetivo.
Veamos cómo podríamos hacer el cálculo usando MapReduce para explotar el
paralelismo natural encontrado en este problema. La entrada son pares clave-valor
( yo, P I), dónde I es una identificación para la foto y PAG I es la imagen en sí. Queremos
Para comparar cada par de imágenes, usemos una clave para cada conjunto de dos ID.
yo, j}. Hay aproximadamente 5 × 10 11 pares de dos ID. Queremos cada uno
llave { yo, j} estar asociado con los dos valores PAG I y PAG j, así que la entrada al
el reductor correspondiente será ({ i, j}, [P I, PAG j]). Entonces, la función Reducir puede
simplemente aplicar la función de similitud s a las dos imágenes de su lista de valores, que
es, computar s (P I, PAG j), y decidir si la similitud de las dos imágenes está por encima
del umbral. El par se emitiría si es así.
Por desgracia, este algoritmo fallará por completo. El tamaño del reductor es pequeño, ya que no
2.6. TEORÍA DE LA COMPLEJIDAD PARA MAPREDUCE 63

La lista tiene más de dos valores, o un total de 2 MB de entrada. Aunque no sabemos


exactamente cómo funciona la similitud s funciona, podemos esperar razonablemente que
no requiera más que la memoria principal disponible. Sin embargo, la tasa de replicación
es 999,999, ya que para cada imagen generamos ese número de pares de valores clave,
uno para cada una de las otras imágenes del conjunto de datos. El número total de bytes
comunicados de Tareas de mapa a Tareas de reducción es 1,000,000 (para las imágenes)
por 999,999 (para la replicación), por 1,000,000 (para el tamaño de cada imagen). Eso es
aproximadamente 10 18 bytes o un exabyte. Para comunicar esta cantidad de datos a
través de Gigabit Ethernet se necesitarían 10 10 segundos, o unos 300 años. 11

Afortunadamente, este algoritmo es solo el punto extremo en un espectro de


posibles algoritmos. Podemos caracterizar estos algoritmos agrupando imágenes en
gramo grupos, cada uno de los 10 6 / gramo imágenes.

La función del mapa: Tome un elemento de entrada ( yo, P I) y generar gramo - 1 pares de valores
clave. Para cada uno, la clave es uno de los conjuntos { u, v}, dónde tu es el grupo a
cuál Foto I pertenece, y v es uno de los otros grupos. El valor asociado es el par ( yo, P
I).

La función de reducción: Considere la clave { u, v}. La lista de valores asociados


tendrá el 2 × 10 6 / gramo elementos j, P j), dónde j pertenece a cualquiera de los
grupos tu o grupo v. La función Reducir toma cada ( yo, P I) y ( j, P j) en esta lista, donde
I y j pertenecen a diferentes grupos, y aplica la función de similitud s (P I, PAG j).
Además, necesitamos comparar las imágenes que pertenecen al mismo grupo,
pero no queremos hacer la misma comparación en cada uno de los gramo - 1 reductores
cuya llave contiene un número de grupo determinado. Hay muchas formas de manejar
este problema, pero una es la siguiente. Comparar los miembros del grupo tu en el
reductor { u, u + 1}, donde el "+1" se toma en el sentido final. Es decir, si u = g ( es decir, tu
es el último grupo), entonces u + 1 es el grupo 1. De lo contrario, u + 1 es el grupo cuyo
número es uno mayor que u.

Podemos calcular la tasa de replicación y el tamaño del reductor en función del número de grupos
gramo. Cada elemento de entrada se convierte en gramo - 1 pares clave-valor. Es decir, la tasa de
replicación es gramo - 1, o aproximadamente r = g, ya que suponemos que el número de grupos sigue
siendo bastante grande. El tamaño del reductor es 2 × 10 6 / gramo, ya que ese es el número de valores
en la lista para cada reductor. Cada valor es de aproximadamente un megabyte, por lo que la cantidad
de bytes necesarios para almacenar la entrada es 2 × 10 12 / gramo.

Ejemplo 2.18: Si gramo es 1000, la entrada consume aproximadamente 2 GB. Eso es


suficiente para guardar todo en una memoria principal típica. Además, el número
total de bytes comunicados ahora es 10 6 × 999 × 10 6, o alrededor de 10 15 bytes. Si
bien todavía es una gran cantidad de datos para comunicar, es 1000 veces menos
que la del algoritmo de fuerza bruta que se discutió primero. Además, hay
11 En un clúster típico, hay muchos conmutadores que conectan subconjuntos de los nodos de cómputo, por lo que no
es necesario que todos los datos pasen por un único conmutador de gigabit. Sin embargo, la comunicación total
disponible es todavía lo suficientemente pequeña como para que no sea factible implementar este algoritmo para la
escala de datos que hemos hipotetizado.
64 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

todavía alrededor de medio millón de reductores. Dado que es poco probable que tengamos
disponibles tantos nodos de cómputo, podemos dividir todos los reductores en un número menor de
tareas de Reducir y seguir manteniendo ocupados todos los nodos de cómputo; es decir, podemos
obtener tanto paralelismo como nuestro clúster informático nos ofrece. ✷

El costo de cálculo de los algoritmos de esta familia es independiente del número


de grupos gramo, siempre que la entrada a cada reductor se ajuste a la memoria
principal. La razón es que la mayor parte del cálculo es la aplicación de la función s
a los pares de imágenes. No importa el valor gramo tiene, s se aplica a cada par una vez y
solo una vez. Por tanto, aunque el trabajo de los algoritmos en la familia puede dividirse
entre los reductores de formas muy diferentes, todos los miembros de la familia realizan el
mismo cálculo.

2.6.3 Un modelo de gráfico para problemas de MapReduce


En esta sección, comenzamos el estudio de una técnica que nos permitirá probar límites
inferiores en la tasa de replicación, en función del tamaño del reductor, para una serie de
problemas. Nuestro primer paso es presentar un modelo gráfico de problemas. Este
gráfico describe cómo las salidas del problema dependen de las entradas. La idea clave a
explotar es que, dado que los reductores operan de forma independiente, para cada salida
debe haber algún reductor que obtenga todas las entradas necesarias para calcular esa
salida. Para cada problema solucionable por un algoritmo MapReduce hay:

1. Un conjunto de entradas.

2. Un conjunto de salidas.

3. Una relación de muchos-muchos entre las entradas y las salidas, que describe
qué entradas son necesarias para producir qué salidas.

Ejemplo 2.19: La figura 2.9 muestra el gráfico para el problema de unión de similitudes
discutido en la sección 2.6.2, si hubiera cuatro imágenes en lugar de un millón. Las
entradas son las imágenes y las salidas son los seis posibles pares de imágenes. Cada
salida está relacionada con las dos entradas que son miembros de su par. Esta forma de
problema, donde las salidas son todos los pares de entradas, es común y nos referiremos
a él como el todos-pares problema. ✷

Ejemplo 2.20: La multiplicación de matrices presenta una gráfica más compleja. Si multiplicamos norte ×
norte matrices METRO y norte para obtener matriz PAG , entonces hay 2 norte 2 entradas,
metro ij y norte jk, y aquí están norte 2 salidas pag ik. Cada salida pag ik está relacionado con 2 norte
entradas: metro I 1, metro I 2,. . . , metro en y norte 1 k, norte 2 k,. . . , norte nk. Además, cada entrada está relacionada
para norte salidas. Por ejemplo, metro ij está relacionado con pag I 1, pag I 2,. . . , pag en. La figura
2.10 muestra la relación entrada-salida para la multiplicación de matrices para el caso simple de
2 × 2 matrices, específicamente

a B mi F I j
=
C D h
gramo k l

2.6. TEORÍA DE LA COMPLEJIDAD PARA MAPREDUCE sesenta y cinco

{ PAG 1, PAG 2}

{ PAG 1, PAG 3}

2
{ PAG 1, PAG 4}

3 { PAG 2, PAG 3}

{ PAG 2, PAG 4}

{ PAG 3, PAG 4}

Figura 2.9: Relación entrada-salida para una unión de similitud

En los problemas de los ejemplos 2.19 y 2.20, las entradas y salidas fueron

claramente todos los presentes. Sin embargo, existen otros problemas en los que las
entradas y / o salidas pueden no estar todas presentes en cualquier instancia del
problema. Un ejemplo de tal problema es la unión natural de R (A, B) y S (B, C)
discutido en la Sección 2.3.7. Asumimos los atributos A, B, y C cada uno tiene un
dominio finito, por lo que sólo hay un número finito de posibles entradas y salidas.
Todas las entradas son posibles R- tuplas, aquellas que consisten en un valor del
dominio de A emparejado con un valor del dominio de B, y todo lo posible S- tuplas:
pares de los dominios de B y C. Las salidas son todas posibles triples, con
componentes de los dominios de A, B, y C en ese orden. La salida ( a B C) está
conectado a dos entradas, a saber R (a, b) y S (b, c).
Pero en una instancia del cálculo de unión, solo estarán presentes algunas de las
posibles entradas y, por lo tanto, solo se producirán algunas de las posibles salidas. Ese
hecho no influye en la gráfica del problema. Todavía necesitamos saber cómo se relaciona
cada salida posible con las entradas, ya sea que esa salida se produzca o no en una
instancia determinada.

2.6.4 Esquemas de mapeo


Ahora que vemos cómo representar los problemas abordables por MapReduce como
gráficos, podemos definir los requisitos para que un algoritmo MapReduce resuelva un
problema dado. Cada uno de estos algoritmos debe tener un esquema de mapeo, que
expresa cómo las salidas son producidas por los diversos reductores usados por el
algoritmo. Es decir, un esquema de mapeo para un problema dado con un tamaño de
reductor dado q es una asignación de entradas a uno o más reductores, de manera que:

1. A ningún reductor se le asigna más de q entradas.


66 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Figura 2.10: Relación insumo-producto para la multiplicación de matrices

2. Para cada salida del problema, hay al menos un reductor al que se le asignan todas
las entradas que están relacionadas con esa salida. Decimos este reductor
cubre La salida.

El punto (1) es simplemente la definición de "tamaño del reductor". El punto (2) se justifica
por el hecho de que los reductores solo pueden ver las entradas que reciben. Si ningún reductor
ve todas las entradas de las que depende una salida, entonces ningún reductor puede producir
correctamente esa salida y, por lo tanto, el supuesto algoritmo no funcionará. Se puede
argumentar que la existencia de un esquema de mapeo para cualquier tamaño de reductor es lo
que distingue los problemas que pueden resolverse con un solo trabajo de MapReduce de los
que no.

Ejemplo 2.21: Reconsideremos la estrategia de "agrupamiento" que discutimos en relación con el


problema de todos los pares en la Sección 2.6.2. Para generalizar el problema, suponga que la
entrada es pag imágenes, que colocamos en gramo grupos de igual tamaño de p / g
entradas cada uno. El número de salidas es pag 2, o aproximadamente pag 2 / 2 salidas. A
reductor obtendrá las entradas de dos grupos, es decir, 2 p / g entradas, por lo que el tamaño
del reductor que necesitamos es q = 2 p / g. Cada imagen se envía a los reductores
correspondientes a las parejas que componen su grupo y cualquiera de los gramo - 1 otros
grupos. Por tanto, la tasa de replicación es gramo - 1, o aproximadamente gramo. Si
reemplazamos gramo por la tasa de replicación r en q = 2 p / g, concluimos que r = 2 p / q. Es
decir, la tasa de replicación es inversamente proporcional al tamaño del reductor. Esa relación es
común; cuanto menor sea el tamaño del reductor, mayor será la tasa de replicación y, por lo
tanto, mayor será la comunicación.
Esta familia de algoritmos se describe mediante una familia de esquemas de mapeo, uno
para cada posible q. En el esquema de mapeo para q = 2 p / g, existen gramo 2, o
aproximadamente gramo 2 / 2 reductores. Cada reductor corresponde a un par de grupos y
una entrada PAG se asigna a todos los reductores cuyo par incluye el grupo de
2.6. TEORÍA DE LA COMPLEJIDAD PARA MAPREDUCE 67

PAG . Por lo tanto, a ningún reductor se le asigna más de 2 p / g insumos; de hecho, a cada
reductor se le asigna exactamente ese número. Además, cada salida está cubierta por
algún reductor. Específicamente, si la salida es un par de dos grupos diferentes tu y v,
entonces esta salida está cubierta por el reductor para el par de grupos { u, v}. Si la salida
corresponde a entradas de un solo grupo u, entonces la salida está cubierta por varios
reductores, los correspondientes al conjunto de grupos { u, v} para cualquier
v 6 = u. Tenga en cuenta que el algoritmo que describimos tiene solo uno de estos
reductores que calcula la salida, pero cualquiera de ellos podría calcularlo. ✷

El hecho de que una salida dependa de una determinada entrada significa que
cuando esa entrada se procesa en la tarea Mapa, habrá al menos un par clave-valor
generado para ser utilizado al calcular esa salida. Es posible que el valor no sea
exactamente la entrada (como fue el caso en el ejemplo 2.21), pero se deriva de esa
entrada. Lo importante es que para cada entrada y salida relacionada hay un par
clave-valor que debe comunicarse. Tenga en cuenta que técnicamente nunca es
necesario más de un par clave-valor para una entrada y salida determinadas, porque
la entrada podría transmitirse al reductor como sí mismo, y las transformaciones en
la entrada aplicadas por la función Map podrían en su lugar ser aplicada por la
función Reducir en el reductor para esa salida.

2.6.5 Cuando no todas las entradas están presentes


El ejemplo 2.21 describe un problema en el que sabemos que todas las entradas posibles están
presentes, porque podemos definir el conjunto de entradas como aquellas imágenes que
realmente existen en el conjunto de datos. Sin embargo, como se discutió al final de la Sección
2.6.3, existen problemas como calcular la combinación, donde el gráfico de entradas y salidas
describe las entradas que podrían existir, y las salidas que solo se generan cuando al menos una
de las entradas existe en el conjunto de datos. De hecho, para la combinación, ambas entradas
relacionadas con una salida deben existir si queremos hacer esa salida.
Un algoritmo para un problema en el que pueden faltar salidas todavía necesita un esquema
de mapeo. La justificación es que todas las entradas, o cualquier subconjunto de ellas,
podría estar presente, por lo que un algoritmo sin un esquema de mapeo no podría
producir todas las salidas posibles si todas las entradas relacionadas con esa salida
estuvieran presentes y, sin embargo, ningún reductor cubriera esa salida.
La única forma en que la ausencia de algunas entradas marca la diferencia es que es posible
que deseemos repensar el valor deseado del tamaño del reductor q cuando seleccionamos un
algoritmo de la familia de posibles algoritmos. Especialmente, si el valor de q
que seleccionamos es ese número de modo que podamos estar seguros de que la entrada encajará en la
memoria principal, entonces es posible que deseemos aumentar q para tener en cuenta que una fracción de los
insumos no está realmente allí.

Ejemplo 2.22: Suponga que sabemos que podemos ejecutar la función Reducir en la memoria
principal en una tecla y su lista asociada de q valores. Sin embargo, también sabemos que solo el
5% de las posibles entradas están realmente presentes en el conjunto de datos. Luego, un
esquema de mapeo para el tamaño del reductor q realmente enviará sobre q / 20 de las
entradas que existen para cada reductor. Dicho de otra manera, podríamos usar el algoritmo
68 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

para reductor tamaño 20 q y esperar que un promedio de q las entradas aparecerán en la lista
para cada reductor. Por tanto, podemos elegir 20 q como el tamaño del reductor, o dado que
habrá cierta aleatoriedad en el número de entradas que realmente aparecen en cada reductor,
es posible que deseemos elegir un valor ligeramente menor del tamaño del reductor, como 18 q.

2.6.6 Límites más bajos en la tasa de replicación


La familia de algoritmos de unión de similitud descrita en el ejemplo 2.21 nos permite
intercambiar comunicación con el tamaño del reductor y, a través del tamaño del reductor,
intercambiar la comunicación con el paralelismo o con la capacidad de ejecutar la función
Reducir en la memoria principal. ¿Cómo sabemos que estamos obteniendo el mejor intercambio
posible? Solo podemos saber que tenemos la mínima comunicación posible si podemos
demostrar un límite inferior coincidente. Usando la existencia de un esquema de mapeo como
punto de partida, a menudo podemos probar ese límite inferior. A continuación se muestra un
resumen de la técnica.

1. Demuestre un límite superior de cuántas salidas tiene un reductor q las entradas pueden
cubrir. Llame a este límite g (q). Este paso puede ser difícil, pero para ejemplos como el
problema de todos los pares, en realidad es bastante simple.

2. Determine el número total de productos producidos por el problema.

3. Suponga que t PAG


aquí están k reductores, y el I El reductor tiene q yo < q entradas.
k
Observa eso yo = 1 g (q I) no debe ser menor que el número de salidas
calculado en el paso (2).
PAG k
4. Manipule la desigualdad de (3) para obtener un límite inferior en yo = 1 q I.
A menudo, el truco utilizado en este paso es reemplazar algunos factores de q I por ellos
ligado
superior PAG q, pero deja un solo factor de q I en el término de I.
k
5. Desde yo = 1 q I es la comunicación total de Tareas de mapa a Tareas de Reducción,
divida el límite inferior de (4) en esta cantidad por el número de entradas.
El resultado es un límite inferior en la tasa de replicación.

Ejemplo 2.23: Esta secuencia de pasos puede parecer misteriosa, pero consideremos
el problema de todos los pares como un ejemplo que esperamos aclare las cosas.
Recuerde que en el ejemplo 2.21 dimos un límite superior en la tasa de replicación
r de r ≤ 2 p / q, dónde pag fue el número de entradas y q era el tamaño del reductor.
Mostraremos un límite inferior en r eso es la mitad de esa cantidad, lo que implica que,
aunque son posibles mejoras en el algoritmo, 12 cualquier reducción en la comunicación
para un tamaño de reductor dado será por un factor de 2 como máximo.
Para el paso (1), observe que si un reductor se q entradas, no puede cubrir más
que q 2, o aproximadamente q 2 / 2 salidas. Para el paso (2), sabemos que hay un

12 De hecho, un algoritmo con r Muy cerca de p / q existe, para al menos algunos valores de pag.
2.6. CO TEORÍA DE LA PLLEXIDAD PARA MAPREDUCE 69

pag
Total de 2, o aproximadamente pag 2 / 2 salidas que deben cubrirse cada una. los
la desigualdad construida en el paso (3) es así

Xk
qI 2/ 2 ≥ pag 2 / 2
yo = 1

o, multiplicando ambos lados por 2,

Xk
qI 2≥ pag 2 ( 2.1)
yo = 1

Ahora, debemos hacer la manipulación del paso (4). Siguiendo la pista, notamos
que hay dos factores de q I en cada término a la izquierda de la Ecuación (2.1), entonces
reemplazamos un factor por q y deja el otro como q I. Ya que q ≥ q I, solo podemos
aumentar el lado izquierdo al hacerlo y, por lo tanto, la desigualdad se mantiene:

Xk
q q I ≥ pag 2
yo = 1

o dividiendo por q:

Xk
qI ≥ p2/ q (2,2)
yo = 1

El paso final, que es el paso (5), es dividir ambos lados PAG k de ecuación 2.2 por
pag, el número de entradas. Como resultado, el lado izquierdo, que es ( yo = 1 q I)/ pag es igual a la
tasa de replicación, y el lado derecho se convierte en p / q. Es decir, hemos probado
el límite inferior en r:
r≥p/q

Como se afirma, esto muestra que la familia de algoritmos del ejemplo 2.21 tiene una tasa de
replicación que es como mucho el doble de la tasa de replicación más baja posible. ✷

2.6.7 Estudio de caso: multiplicación de matrices


En esta sección aplicaremos la técnica del límite inferior a los algoritmos de multiplicación
de matrices de un paso. Vimos uno de esos algoritmos en la Sección 2.3.10, pero ese es
solo un caso extremo de una familia de posibles algoritmos. En particular, para ese
algoritmo, un reductor corresponde a un solo elemento de la matriz de salida. Así como
agrupamos las entradas en el problema de todos los pares para reducir la comunicación a
expensas de un tamaño de reductor más grande, podemos agrupar filas y columnas de las
dos matrices de entrada en bandas. Cada par que consta de una banda de filas de la
primera matriz y una banda de columnas de la segunda matriz es utilizado por un reductor
para producir un cuadrado de elementos de la matriz de salida. La figura 2.11 sugiere un
ejemplo.
70 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Figura 2.11: División de matrices en bandas para reducir la comunicación

Con más detalle, suponga que queremos calcular MN = P, y las tres matrices son norte ×
norte. Agrupa las filas de METRO dentro gramo bandas de n / g filas cada una, y agrupar las
columnas de norte dentro gramo bandas de n / g columnas cada una. Esta agrupación es como
sugiere la figura 2.11. Las claves corresponden a dos grupos (bandas), uno de METRO y uno de
NORTE.
La función del mapa: Para cada elemento de METRO, la función Mapa genera gramo
pares clave-valor. El valor en cada caso es el propio elemento, junto con su número de fila
y columna para que pueda ser identificado por la función Reducir. La clave es el grupo al
que pertenece el elemento, emparejado con cualquiera de los grupos de la matriz NORTE.
Del mismo modo, para cada elemento de NORTE, la función Mapa genera
gramo pares clave-valor. La clave es el grupo de ese elemento emparejado con cualquiera
de los grupos de METRO, y el valor es el elemento en sí más su fila y columna.
La función de reducción: El reductor correspondiente a la llave ( yo, j), dónde I
es un grupo de METRO y j es un grupo de NORTE, obtiene una lista de valores que consta de
todos los elementos de la I th banda de METRO y el j th banda de NORTE. Por tanto, tiene todos
los valores que necesita para calcular los elementos de PAG cuya fila es una de esas filas que
comprenden el I th banda de METRO y cuya columna es una de las que componen el
j th banda de NORTE. Por ejemplo, la figura 2.11 sugiere el tercer grupo de METRO y el
cuarto grupo de NORTE, combinar para calcular un cuadrado de PAG en el reductor (3, 4).

Cada reductor obtiene n (n / g) elementos de cada una de las dos matrices, por lo que q =
2 norte 2 / gramo. La tasa de replicación es gramo, ya que cada elemento de cada matriz se envía a
gramo reductores. Es decir, r = g. Combinatorio r = g con q = 2 norte 2 / gramo podemos concluir que r =
2 norte 2 / q. Es decir, al igual que para la combinación de similitud, la tasa de replicación varía
inversamente con el tamaño del reductor.
Resulta que este límite superior de la tasa de replicación también es un límite inferior.
Es decir, no podemos hacerlo mejor que la familia de algoritmos que describimos
anteriormente en una sola ronda de MapReduce. Curiosamente, veremos que podemos
obtener una comunicación total menor para el mismo tamaño de reductor, si usamos dos
pasadas de MapReduce como discutimos en la Sección 2.3.9. No daremos la prueba
completa del límite inferior, pero sugeriremos los elementos importantes.
2.6. TEORÍA DE LA COMPLEJIDAD PARA MAPREDUCE 71

Para el paso (1) necesitamos obtener un límite superior de cuántas salidas tiene un reductor de
tamaño q puede cubrir. Primero, observe que si un reductor obtiene algunos de los elementos en una
fila de METRO, pero no todos, entonces los elementos de esa fila son inútiles; el reductor no puede
producir ninguna salida en esa fila de PAG . De manera similar, si un reductor recibe una parte, pero no
la totalidad, de una columna de NORTE, estas entradas también son inútiles. Por lo tanto, podemos
suponer que el mejor esquema de mapeo enviará a cada reductor un número de filas completas de
METRO y algunas columnas completas de NORTE. Este reductor
entonces es capaz de producir el elemento de salida pag ik si y solo si ha recibido la
totalidad I la fila de METRO y todo k a columna de NORTE. El resto del
El argumento del paso (1) es demostrar que se cubre el mayor número de salidas
cuando el reductor recibe el mismo número de filas que de columnas. Dejamos esta
parte como ejercicio.
Sin embargo, asumiendo que un reductor recibe k filas de METRO y k columnas de NORTE,
luego q = 2 nk, y k 2 las salidas están cubiertas. Es decir, g (q), el número máximo de salidas
cubiertas por un reductor que recibe q entradas, es q 2 / 4 norte 2.
Para el paso (2), sabemos que el número de salidas es norte 2. En el paso (3)
observamos que si hay k reductores, con el I reductor recibiendo q ≤ qI entradas, entonces

Xk
q 24 norte
I/ 2≥ norte 2
yo = 1

o
Xk
qI ≥2 4 norte 4
yo = 1

De esta desigualdad, puedes derivar

r ≥ 2 norte 2 / q

Dejamos la manipulación algebraica, que es similar a la del ejemplo 2.23, como


ejercicio.
Ahora, consideremos la generalización del algoritmo de multiplicación de matrices de
dos pasos que describimos en la Sección 2.3.9. Primero, observe que podríamos haber
diseñado la primera pasada para usar un reductor por cada triple ( yo, j, k). Este reductor
obtendría solo los dos elementos metro ij y norte jk. Podemos generalizar esta idea para usar reductores
que obtengan conjuntos más grandes de elementos de cada matriz; estos conjuntos de
los elementos forman cuadrados dentro de sus respectivas matrices. La idea se sugiere en la
figura 2.12. Podemos dividir las filas y columnas de ambas matrices de entrada. METRO
y norte dentro gramo grupos de n / g filas o columnas cada una. Las intersecciones de los grupos
dividen cada matriz en gramo 2 cuadrados de norte 2 / gramo 2 elementos cada uno.
El cuadrado de METRO correspondiente al conjunto de filas I y conjunto de columnas J se
combina con el cuadrado de norte correspondiente al conjunto de filas J y conjunto de columnas
K. Estos dos cuadrados calculan algunos de los términos necesarios para producir el cuadrado
de la matriz de salida. PAG que tiene un conjunto de filas I y conjunto de columnas K.
Sin embargo, estos dos cuadrados no calculan el valor total de estos elementos de
PAG ; más bien producen una contribución a la suma. Otros pares de cuadrados, uno
72 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

Figura 2.12: Partición de matrices en cuadrados para un algoritmo MapReduce de


dos pasos

de METRO y uno de NORTE, contribuir al mismo cuadrado de PAG . Estas contribuciones se


sugieren en la figura 2.12. Allí, vemos cómo todos los cuadrados de METRO con un valor fijo para
un conjunto de filas I emparejar con todos los cuadrados de norte que tienen un valor fijo para el
conjunto de columnas K dejando que el set J variar.
Entonces, en el primer paso, calculamos los productos del cuadrado ( Yo, j) de METRO con el
cuadrado J, K) de NORTE, para todos Yo, j y K. Luego, en la segunda pasada, para cada
I y K sumamos los productos en todos los conjuntos posibles J. Con más detalle, el primer trabajo
de MapReduce hace lo siguiente.
La función del mapa: Las claves son triples de conjuntos de filas y / o números de columna.
bers I, J, K). Supongamos que el elemento metro ij pertenece al grupo de filas I y grupo de
columnas J. Entonces de metro ij generamos gramo pares clave-valor con valor igual a
metro ij, junto con sus números de fila y columna, I y j, para identificar el elemento de la
matriz. Hay un par clave-valor para cada clave ( Yo, j, k), dónde K puede ser cualquiera
de El gramo grupos de columnas de NORTE. Del mismo modo, from element norte jk de NORTE,
si j pertenece al grupo J y k para agrupar K, la función Mapa genera gramo pares clave-valor
con valor que consiste en norte jk, j, y k, y con llaves Yo, j, k) para cualquier grupo I.
La función de reducción: El reductor correspondiente a ( Yo, j, k) recibe como
ingrese todos los elementos metro ij dónde I es en I y j es en J y tambien recibe todo
los elementos norte jk, dónde j es en J y X k es en K. Calcula

X iJk = metro ij norte jk

jInJ
2.6. TEORÍA DE LA COMPLEJIDAD PARA MAPREDUCE 73

para todos I en I y k en K.
Observe que la tasa de replicación para el primer trabajo de MapReduce es gramo, y la

comunicación total es por tanto 2 gn 2. También n pag otice que cada reductor obtiene 2 norte 2 / gramo 2
entradas, entonces q = 2 norte 2 / gramo 2. Equivalentemente, g = n √ 2 / q. √ Así, la comunicación total 2
gn 2 se puede escribir en términos de q como 2 2 norte 3 / q.
El segundo trabajo de MapReduce es simple; resume el X iJk ha terminado todos los conjuntos J.

La función del mapa: Suponemos que las tareas de mapa se ejecutan en los nodos de
cálculo que ejecutaron las tareas de reducción del trabajo anterior. Por lo tanto, no se
necesita comunicación entre los trabajos. La función Mapa toma como entrada uno
elemento X iJk, que suponemos que los reductores anteriores han dejado etiquetados con I
y k para que sepamos a qué elemento de la matriz PAG este término contribuye. Uno
Se genera el par clave-valor. La clave es ( yo, k) y el valor es X iJk.
La función de reducción: La función Reducir simplemente suma los valores asociados con
la clave ( yo, k) para calcular el elemento de salida PAG ik.

La comunicación entre las tareas Mapa y Reducir del segundo trabajo es


gn 2, puesto que hay norte posibles valores de en posibles valores de k, y gramo posible
valores del conjunto J y cada X iJk se comunica onl pag y una vez. Si recordamos de
nuestro análisis del primer trabajo MapReduce th √a g = n 2 / q, podemos escribir el

comunicación para el segundo trabajo como norte 2 g = 2 norte 3 / q. Esta cantidad es exactamente
la mitad de la comunicación √ para th √
mi primer trabajo, así que el total la comunicación para el
el algoritmo de dos pasos es 3 2 norte 3 / q. Aunque lo haremos no examinar este punto
aquí, resulta que podemos hacerlo un poco mejor si dividir las matrices METRO
y norte no en cuadrados sino en rectángulos que son dos veces más largos en un lado que
o √ n el otro. En ese caso, obtenemos la constante 4 ligeramente más pequeña en su lugar
de 3 √ 2 = 4.24, y obtenemos un algoritmo de dos pasos con comunicación igual a 4 norte
3 / q.

Ahora, recuerde que el costo de comunicación que calculamos para el algoritmo de una
pasada es 4 norte 4 / q. Bien podemos asumir q es menos que norte 2, o de lo contrario podemos
solo usa como √ erial en un nodo de cálculo y no utilizar MapReduce en absoluto. Por lo
tanto, norte 3 / q es más pequeña que norte 4 / q, y si q está cerca de su mínimo posible
3 entonces el algoritmo de dos pasadas supera al algoritmo de una pasada por un
valor de 2 norte, 1 √
Factor de Sobre) en comunicación. Además, podemos esperar que la diferencia en la
comunicación sea la diferencia de costos significativa. Ambos algoritmos hacen lo mismo
Sobre 3) operaciones aritmeticas. El método de dos pasadas naturalmente tiene más tareas
de administración de gastos generales que el método de un trabajo. Por otro lado, el
segundo paso del algoritmo de dos pasos aplica una función Reducir que es asociativa y
conmutativa. Por lo tanto, podría ser posible ahorrar algunos costos de comunicación
utilizando un combinador en esa pasada.

2.6.8 Ejercicios para la sección 2.6


Ejercicio 2.6.1: Describe las gráficas que modelan los siguientes problemas.
13 Si q es menor que 2 norte, entonces un reductor no puede obtener ni siquiera una fila y una columna y, por lo tanto,

no puede calcular ninguna salida.


74 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

(a) La multiplicación de un norte × norte matriz por un vector de longitud norte.

(b) La unión natural de R (A, B) y S (B, C), dónde A, B, y C tienen dominios de


tamaños a, b, y C, respectivamente.

(c) La agrupación y agregación en la relación R (A, B), dónde A es el atributo de


agrupación y B es agregado por la operación MAX. Asumir
A y B tener dominios de tamaño a y B, respectivamente.

! Ejercicio 2.6.2: Proporcione los detalles de la prueba de que un algoritmo de multiplicación


de matriz de un paso requiere una tasa de replicación al menos r ≥ 2 norte 2 / q, incluso:

(a) La prueba de que, para un reductor de tamaño fijo, el número máximo de salidas está
cubierto por un reductor cuando ese reductor recibe un número igual de filas de
METRO y columnas de NORTE.
PAG
k
(b) La manipulación algebraica necesaria, comenzando con yo = 1 q 2
I≥ 4 norte 4.

!! Ejercicio 2.6.3: Supongamos que nuestras entradas son cadenas de bits de longitud B, y las salidas
corresponden a pares de cuerdas a una distancia de Hamming 1. 14

(a) Demuestre que un reductor de tamaño q puede cubrir como máximo q / 2) registro 2 q salidas.

(b) Utilice el inciso a) para mostrar el límite inferior de la tasa de replicación: r ≥ B/ Iniciar sesión 2 q.

(c) Demuestre que existen algoritmos con la tasa de replicación dada por el inciso
(b) para los casos q = 2, q = 2 B, y q = 2 B/ 2.

!! Ejercicio 2.6.4: Para pag que es el cuadrado de un primo, muestra que hay un
esquema de mapeo para el problema de todos los pares que ha r ≤ 1 + p / q.

2.7 Resumen del capítulo 2


✦ Computación en clúster: Una arquitectura común para aplicaciones a gran escala
ciones es un grupo de nodos de cómputo (chip del procesador, memoria principal y disco). Los
nodos informáticos se montan en bastidores y los nodos de un bastidor están conectados,
normalmente mediante Gigabit Ethernet. Los racks también están conectados mediante una red
o conmutador de alta velocidad.

✦ Sistemas de archivos distribuidos: Una arquitectura para sistemas de archivos a gran escala
tems se ha desarrollado recientemente. Los archivos se componen de fragmentos de
aproximadamente 64 megabytes, y cada fragmento se replica varias veces, en diferentes nodos
informáticos o racks.

14 Las cadenas de bits tienen Distancia de Hamming 1 si difieren en exactamente una posición de bit. Puede
consultar la Sección 3.5.6 para conocer la definición general.
2.7. RESUMEN DEL CAPITULO 2 75

✦ Mapa reducido: Este sistema de programación permite explotar el paralelismo


inherente a la computación en clúster y administra las fallas de hardware que pueden
ocurrir durante una computación larga en muchos nodos. Muchas tareas de mapa y
muchas tareas de reducción se gestionan mediante un proceso maestro. El maestro
vuelve a ejecutar las tareas en un nodo de cálculo fallido.

✦ La función del mapa: Esta función la escribe el usuario. Toma un


colección de objetos de entrada y convierte cada uno en cero o más pares clave-valor. Las
claves no son necesariamente únicas.

✦ La función de reducción: Un sistema de programación MapReduce ordena todos los


Los pares clave-valor producidos por todas las tareas del mapa, forman todos los valores
asociados con una clave determinada en una lista y distribuyen los pares clave-lista para
reducir las tareas. Cada tarea de Reducir combina los elementos de cada lista, aplicando
la función escrita por el usuario. Los resultados producidos por todas las tareas de
Reducir forman el resultado del proceso MapReduce.

✦ Reductores: A menudo es conveniente referirse a la aplicación de Reducir


función a una sola tecla y su lista de valores asociada como un "reductor".

✦ Hadoop: Este sistema de programación es una implementación de código abierto de un


sistema de archivos distribuidos (HDFS, el sistema de archivos distribuido de
Hadoop) y MapReduce (el propio Hadoop). Está disponible a través de Apache
Foundation.

✦ Gestión de fallos en el nodo informático: Los sistemas MapReduce admiten el reinicio


de tareas que fallan porque su nodo de cómputo, o el bastidor que contiene ese
nodo, falla. Debido a que las tareas de Mapeo y Reducción entregan su salida solo
después de que terminan (la propiedad de bloqueo), es posible reiniciar una tarea
fallida sin preocuparse por la posible repetición de los efectos de esa tarea. Es
necesario reiniciar todo el trabajo solo si falla el nodo en el que se ejecuta el
maestro.

✦ Aplicaciones de MapReduce: Si bien no todos los algoritmos paralelos son adecuados


para su implementación en el marco MapReduce, existen implementaciones
simples de multiplicación matriz-vector y matriz-matriz. Además, los principales
operadores del álgebra relacional se implementan fácilmente en MapReduce.

✦ Sistemas de flujo de trabajo: MapReduce se ha generalizado a sistemas que soportan


portar cualquier colección acíclica de funciones, cada una de las cuales puede ser
instanciada por cualquier número de tareas, cada una responsable de ejecutar esa
función en una porción de los datos.

✦ Chispa - chispear: Este popular sistema de flujo de trabajo presenta Resilient, Distributed
Conjuntos de datos (RDD) y un lenguaje en el que se pueden escribir muchas operaciones
comunes en RDD. Spark tiene una serie de eficiencias, incluida la evaluación perezosa de
los RDD para evitar el almacenamiento secundario de resultados intermedios.
76 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

y el registro del linaje de los RDD para que puedan reconstruirse según sea
necesario.

✦ TensorFlow: Este sistema de flujo de trabajo está específicamente diseñado para respaldar
aprendizaje automático. Los datos se representan como matrices multidimensionales, o
tensores, y las operaciones integradas realizan muchas operaciones poderosas, como el álgebra
lineal y el entrenamiento de modelos.

✦ Flujos de trabajo recursivos: Al implementar una colección recursiva de funciones


Además, no siempre es posible conservar la capacidad de reiniciar cualquier tarea
fallida, porque las tareas recursivas pueden haber producido resultados que fueron
consumidos por otra tarea antes de la falla. Se han propuesto varios esquemas para
señalar partes del cálculo para permitir el reinicio de tareas individuales, o reiniciar
todas las tareas desde un punto reciente.

✦ Costo de comunicación: Muchas aplicaciones de MapReduce o sistemas similares


Los tems hacen cosas muy simples para cada tarea. Entonces, el costo
dominante suele ser el costo de transportar los datos desde donde se crean
hasta donde se utilizan. En estos casos, la eficiencia de un algoritmo
MapReduce se puede estimar calculando la suma de los tamaños de las
entradas a todas las tareas.

✦ Uniones de múltiples vías: A veces es más eficiente replicar tuplas del


relaciones involucradas en una combinación y tienen la combinación de tres o más
relaciones calculadas como un solo trabajo MapReduce. La técnica de los multiplicadores
de Lagrange se puede utilizar para optimizar el grado de replicación de cada una de las
relaciones participantes.

✦ Estrella se une: Las consultas analíticas a menudo implican una tabla de hechos muy grande unida
con tablas de dimensiones más pequeñas. Estas uniones siempre se pueden realizar de forma
eficiente mediante la técnica de unión de múltiples vías. Una alternativa es distribuir la tabla de
hechos y replicar las tablas de dimensiones de forma permanente, usando la misma estrategia
que se usaría si estuviéramos tomando la combinación de múltiples vías de la tabla de hechos y
cada tabla de dimensiones.

✦ Tasa de replicación y tamaño del reductor: Suele ser conveniente medir


comunicación por la tasa de replicación, que es la comunicación por entrada.
Además, el tamaño del reductor es el número máximo de entradas asociadas con
cualquier reductor. Para muchos problemas, es posible derivar un límite inferior en
la tasa de replicación en función del tamaño del reductor.

✦ Representar problemas como gráficos: Es posible representar muchos problemas


lemas que son susceptibles de cálculo MapReduce mediante un gráfico en el que los
nodos representan entradas y salidas. Una salida está conectada a todas las
entradas que se necesitan para calcular esa salida.

✦ Esquemas de mapeo: Dada la gráfica de un problema, y dado un tamaño de reductor,


un esquema de mapeo es una asignación de las entradas a uno o más reductores
2.8. REFERENCIAS DEL CAPÍTULO 2 77

de modo que a ningún reductor se le asignen más entradas de las que permite el tamaño
del reductor y, sin embargo, para cada salida hay algún reductor que obtiene todas las
entradas necesarias para calcular esa salida. El requisito de que haya un esquema de
mapeo para cualquier algoritmo de MapReduce es una buena expresión de lo que hace
que los algoritmos de MapReduce sean diferentes de los cálculos paralelos generales.

✦ Multiplicación de matrices por MapReduce: Hay una familia de Map-


Reducir los algoritmos que realizan la multiplicación de norte × norte matrices con la
mínima tasa de replicación posible r = 2 norte 2 / q, dónde q es el tamaño del reductor. Por
otro lado, un algoritmo MapReduce de dos pasadas para el mismo problema con el
mismo tamaño de reductor puede usar hasta un factor de norte menos comunicación.

2.8 Referencias del Capítulo 2


GFS, el sistema de archivos de Google, se describió en [13]. El documento sobre
MapReduce de Google es [10]. Puede encontrar información sobre Hadoop y HDFS en [15].
Se pueden encontrar más detalles sobre relaciones y álgebra relacional en [25].
Varios de los primeros sistemas de flujo de trabajo fueron Clustera [11] en la
Univ. de Wisconsin y Hyracks (anteriormente llamado Hyrax) [6], de UC Irvine, y Dryad
de Microsoft [17] y más tarde DryadLINQ [26].
Flink es un sistema de flujo de trabajo de código abierto diseñado para manejar datos de transmisión
[12]. Fue desarrollado originalmente en el proyecto Stratosphere [5] en TU Berlín.
Muchas de las innovaciones de Spark se describen en [27]. La implementación de
código abierto de Spark está en [21]. La página de información sobre TensorFlow es
[24].
El enfoque de MapReduce iterado para implementar la recursividad es de Haloop [7]. Para
una discusión sobre la implementación de la recursividad en clústeres, consulte [1].
Pregel es de [19]. Existe una versión de código abierto de Pregel llamada Giraph
[14]. GraphLab [18] es otro notable sistema de implementación paralela para
algoritmos gráficos. GraphX [22] es una interfaz gráfica para Spark.
Hay una serie de otros sistemas construidos en un sistema de archivos
distribuidos y / o MapReduce, que no se han cubierto aquí, pero que puede valer la
pena conocer. [8] describe Mesa grande, una implementación de Google de una
tienda de objetos de gran tamaño. Yahoo! con Nueces
[9]. Este último admite una forma limitada de procesamiento de transacciones, por ejemplo.
CERDO [ 20] es una implementación de álgebra relacional sobre Hadoop. Similar,
Colmena [ 16] implementa una forma restringida de SQL sobre Hadoop. Spark también
proporciona una interfaz similar a SQL [23].
El modelo de costo de comunicación para los algoritmos de MapReduce y las
implementaciones óptimas de uniones de múltiples vías es de [3]. El material sobre la tasa de
replicación, el tamaño del reductor y su relación es de [2]. Soluciones de los ejercicios 2.6.2 y
2.6.3 se puede encontrar allí. La solución del ejercicio 2.6.4 está en [4].
78 CAPÍTULO 2. MAPREDUCE Y LA NUEVA PILA DE SOFTWARE

1. FN Afrati, V. Borkar, M. Carey, A. Polyzotis y JD Ullman, "Cluster computing,


recursión y registro de datos", que aparecerá en Proc. Taller Datalog 2.0,
Elsevier, 2011.

2. FN Afrati, A. Das Sarma, S. Salihoglu y JD Ullman, "Límites superior e inferior del


costo de un cálculo de MapReduce". Aparecer en
Proc. Intl. Conf. en bases de datos muy grandes, 2013. También disponible como CoRR,
abs / 1206.4377.

3. FN Afrati y JD Ullman, "Optimización de uniones en un entorno MapReduce", Proc.


Decimotercera Intl. Conf. sobre la ampliación de la tecnología de bases de datos,
2010.

4. FN Afrati y JD Ullman, "Coincidencia de límites para el problema de MapReduce de


todos los pares", IDEAS 2013, págs. 3-4.

5. A. Alexandrov, R. Bergmann, S. Ewen, J.-C. Freytag, F. Hueske, A. Heise O. Kao,


M. Leich, U. Leser, V. Markl, F. Naumann, M. Peters,
A. Rheinlander, MJ Sax, S. Schelter, M. Hoger, K. Tzoumas y D. Warneke, "La
plataforma Stratosphere para el análisis de macrodatos", VLDB J.
23: 6, págs. 939–964, 2014.

6. VR Borkar, MJ Carey, R, Grover, N. Onose y R. Vernica, "Hyracks: una base


flexible y extensible para la informática con uso intensivo de datos", Intl. Conf.
en Ingeniería de Datos, págs. 1151-1162, 2011.

7. Y. Bu, B. Howe, M. Balazinska y M. Ernst, "HaLoop: e ffi cient iterative data


processing on large clusters", Proc. Intl. Conf. en bases de datos muy grandes,
2010.

8. F. Chang, J. Dean, S. Ghemawat, WC Hsieh, DA Wallach, M. Burrows,


T. Chandra, A. Fikes y RE Gruber, "Bigtable: un sistema de almacenamiento
distribuido para datos estructurados", Transacciones ACM en sistemas informáticos
26: 2, págs. 1 a 26, 2008.

9. BF Cooper, R. Ramakrishnan, U. Srivastava, A. Silberstein, P. Bohannon, H.-A.


Jacobsen, N. Puz, D. Weaver y R. Yerneni, "Pnuts: la plataforma de servicio de
datos alojados de Yahoo!" PVLDB 1: 2, págs. 1277–1288, 2008.

10. J. Dean y S. Ghemawat, "Mapreduce: simpli fi ed data processing on large


clusters", Comm. ACM 51: 1, págs. 107-113, 2008.

11. DJ DeWitt, E. Paulson, E. Robinson, JF Naughton, J. Royalty, S. Shankar y A.


Krioukov, "Clustera: an Integrated Computation and Data Management
System", PVLDB 1: 1, págs. 28–41, 2008.

12. flink.apache.org, Fundación Apache.

13. S. Ghemawat, H. Gobio ff y S.-T. Leung, "El sistema de archivos de Google",


XIX Simposio de ACM sobre principios de sistemas operativos, 2003.
2.8. REFERENCIAS DEL CAPÍTULO 2 79

14. giraph.apache.org, Fundación Apache.

15. hadoop.apache.org, Fundación Apache.

dieciséis. hadoop.apache.org/hive, Fundación Apache.

17. M. Isard, M. Budiu, Y. Yu, A. Birrell y D. Fetterly. "Dríada: dis-


programas paralelos de datos tributos a partir de bloques de construcción
secuenciales ", Actas de la 2a Conferencia europea ACM SIGOPS / EuroSys sobre
sistemas informáticos, págs. 59–72, ACM, 2007.

18. Y. Low, D. Bickson, J. González, C. Guestrin, A. Kyrola y JM Hellerstein,


“Distributed GraphLab: un marco para el aprendizaje automático y la minería
de datos en la nube”, em Proc. Dotación VLDB 5: 8, págs. 716–727,
2012.

19. G. Malewicz, MN Austern, AJC Sik, JC Denhert, H. Horn, N. Leiser y G. Czajkowski,


"Pregel: a system for large-scale graph processing",
Proc. Conferencia ACM SIGMOD, 2010.

20. C. Olston, B. Reed, U. Srivastava, R. Kumar y A. Tomkins, "Pig latin: a not-so-


Foreign language for data processing", Proc. Conferencia ACM SIGMOD, págs.
1099-1110, 2008.

21. spark.apache.org, Fundación Apache.

22. spark.apache.org/graphx, Fundación Apache.

23. spark.apache.org/sql, Fundación Apache.

24. www.tensorflow.org.

25. JD Ullman y J. Widom, Un primer curso en sistemas de bases de datos, Tercera


edición, Prentice-Hall, Upper Saddle River, Nueva Jersey, 2008.

26. Y. Yu, M. Isard, D. Fetterly, M. Budiu, I. Erlingsson, PK Gunda y


J. Currey, "DryadLINQ: un sistema para computación paralela de datos distribuidos
de uso general que utiliza un lenguaje de alto nivel", OSDI, págs. 1-14, Asociación
USENIX, 2008.

27. M. Zaharia, M. Chowdhury, T. Das, A. Dave, J. Ma, M. McCauley, MJ Franklin, S.


Shenker e I. Stoica, “Conjuntos de datos distribuidos resilientes: una
abstracción tolerante a fallas para -computación en clúster de memoria " Proc.
9a conferencia de USENIX sobre diseño e implementación de sistemas en red,
Asociación USENIX, 2012.

También podría gustarte