Está en la página 1de 7

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

com

Spark: computación en clúster con conjuntos de trabajo

Matei Zaharia, Mosharaf Chowdhury, Michael J. Franklin, Scott Shenker, Ion Stoica
Universidad de California, Berkeley

Abstracto MapReduce/Dryad, cada trabajo debe recargar los datos del disco, lo
que genera una penalización significativa en el rendimiento.
MapReduce y sus variantes han tenido mucho éxito en la
implementación de aplicaciones intensivas en datos a gran • Análisis interactivo:Hadoop se usa a menudo para ejecutar

escala en clústeres de productos básicos. Sin embargo, la consultas exploratorias ad-hoc en grandes conjuntos de datos, a

mayoría de estos sistemas se basan en un modelo de flujo de través de interfaces SQL como Pig [21] y Hive [1]. Idealmente, un

datos acíclico que no es adecuado para otras aplicaciones usuario podría cargar un conjunto de datos de interés en la

populares. Este documento se centra en una de esas clases memoria de varias máquinas y consultarlo repetidamente. Sin

de aplicaciones: aquellas que reutilizan un conjunto de datos embargo, con Hadoop, cada consulta incurre en una latencia

de trabajo en múltiples operaciones paralelas. Esto incluye significativa (decenas de segundos) porque se ejecuta como un

muchos algoritmos iterativos de aprendizaje automático, así trabajo de MapReduce independiente y lee datos del disco.

como herramientas interactivas de análisis de datos. Este documento presenta un nuevo marco de computación en
Proponemos un nuevo marco llamado Spark que admite clúster llamado Spark, que admite aplicaciones con conjuntos de
estas aplicaciones mientras conserva la escalabilidad y la trabajo y proporciona propiedades de escalabilidad y tolerancia a
tolerancia a fallas de MapReduce. Para lograr estos objetivos, fallas similares a las de MapReduce.
Spark presenta una abstracción llamada conjuntos de datos La principal abstracción en Spark es la de unconjunto de datos
distribuidos resilientes (RDD). Un RDD es una colección de distribuido resiliente(RDD), que representa una colección de objetos
objetos de solo lectura particionados en un conjunto de de solo lectura particionados en un conjunto de máquinas que se
máquinas que se pueden reconstruir si se pierde una pueden reconstruir si se pierde una partición. Los usuarios pueden
partición. almacenar en caché explícitamente un RDD en la memoria en todas
las máquinas y reutilizarlo en múltiples aplicaciones similares a
1. Introducción
MapReduce.operaciones paralelas. Los RDD logran tolerancia a fallas
Un nuevo modelo de computación en clúster se ha vuelto muy popular, en a través de una noción delinaje: si se pierde una partición de un RDD,
el que los cálculos paralelos de datos se ejecutan en clústeres de máquinas el RDD tiene suficiente información sobre cómo se derivó de otros
poco confiables mediante sistemas que proporcionan automáticamente RDD para poder reconstruir solo esa partición. Aunque los RDD no
programación consciente de la localidad, tolerancia a fallas y balanceo de son una abstracción general de memoria compartida, representan un
carga. MapReduce [11] fue pionero en este modelo, mientras que sistemas punto óptimo entre la expresividad por un lado y la escalabilidad y
como Dryad [17] y Map-Reduce-Merge [24] generalizaron los tipos de flujos confiabilidad por el otro, y los hemos encontrado muy adecuados
de datos admitidos. Estos sistemas logran su escalabilidad y tolerancia a para una variedad de aplicaciones.
fallas al proporcionar un modelo de programación donde el usuario crea Spark se implementa en Scala [5], un lenguaje de
gráficos de flujo de datos acíclicos para pasar datos de entrada a través de programación de alto nivel tipificado estáticamente para Java
un conjunto de operadores. Esto permite que el sistema subyacente VM, y expone una interfaz de programación funcional similar a
administre la programación y reaccione ante fallas sin la intervención del DryadLINQ [25]. Además, Spark se puede utilizar de forma
usuario. interactiva desde una versión modificada del intérprete de Scala,
Si bien este modelo de programación de flujo de datos es útil para una que permite al usuario definir RDD, funciones, variables y clases
amplia clase de aplicaciones, hay aplicaciones que no se pueden expresar y utilizarlos en operaciones paralelas en un clúster. Creemos que
de manera eficiente como flujos de datos acíclicos. En este documento, nos Spark es el primer sistema que permite el uso interactivo de un
centramos en una de esas clases de aplicaciones: aquellas que reutilizan un lenguaje de programación eficiente y de propósito general para
conjunto de trabajode datos a través de múltiples operaciones paralelas. procesar grandes conjuntos de datos en un clúster.
Esto incluye dos casos de uso en los que hemos visto a usuarios de Hadoop Aunque nuestra implementación de Spark aún es un prototipo, la
informar que MapReduce es deficiente: experiencia inicial con el sistema es alentadora. Mostramos que Spark

• Trabajos iterativos:Muchos algoritmos comunes de aprendizaje puede superar a Hadoop en 10 veces en cargas de trabajo iterativas de

automático aplican una función repetidamente al mismo conjunto de aprendizaje automático y se puede usar de forma interactiva para escanear

datos para optimizar un parámetro (p. ej., a través del descenso de un conjunto de datos de 39 GB con una latencia inferior a un segundo.

gradiente). Si bien cada iteración se puede expresar como un Este artículo está organizado de la siguiente forma: La sección 2 describe

1
Modelo de programación de Spark y RDD. La sección 3 muestra algunos – Elahorraraction evalúa el conjunto de datos y lo escribe en
trabajos de ejemplo. La Sección 4 describe nuestra implementación, un sistema de archivos distribuido como HDFS. La versión
incluida nuestra integración en Scala y su intérprete. La Sección 5 presenta guardada se utiliza en futuras operaciones sobre ella.
los primeros resultados. Examinamos el trabajo relacionado en la Sección 6 Hacemos notar que nuestrocacheLa acción es solo una sugerencia: si no hay
y terminamos con una discusión en la Sección 7. suficiente memoria en el clúster para almacenar en caché todas las particiones
de un conjunto de datos, Spark las volverá a calcular cuando se usen. Elegimos
2 Modelo de programación
este diseño para que los programas de Spark sigan funcionando (con un
Para usar Spark, los desarrolladores escriben unprograma de rendimiento reducido) si los nodos fallan o si un conjunto de datos es demasiado
controladorque implementa el flujo de control de alto nivel de su grande. Esta idea es vagamente análoga a la memoria virtual.
aplicación y lanza varias operaciones en paralelo. Spark proporciona También planeamos ampliar Spark para admitir otros niveles de
dos abstracciones principales para la programación paralela: persistencia (p. ej., replicación en memoria en varios nodos). Nuestro
conjuntos de datos distribuidos resilientesyoperaciones paralelasen objetivo es permitir que los usuarios compensen entre el costo de
estos conjuntos de datos (invocado al pasar una función para aplicar almacenar un RDD, la velocidad de acceso a él, la probabilidad de
en un conjunto de datos). Además, Spark admite dos tipos perder parte de él y el costo de volver a calcularlo.
restringidos devariables compartidasque se puede usar en funciones
que se ejecutan en el clúster, que explicaremos más adelante. 2.2 Operaciones paralelas

2.1 Conjuntos de datos distribuidos resilientes (RDD) Se pueden realizar varias operaciones paralelas en los RDD:

Un conjunto de datos distribuido resistente (RDD) es una colección de


• reducir: combina elementos del conjunto de datos usando una función
asociativa para producir un resultado en el programa controlador.
objetos de solo lectura particionados en un conjunto de máquinas que se
pueden reconstruir si se pierde una partición. No es necesario que los • recolectar: envía todos los elementos del conjunto de datos al

elementos de un RDD existan en almacenamiento físico; en cambio, un programa controlador. Por ejemplo, una forma sencilla de actualizar

identificador de un RDD contiene suficiente información paracalcularel un arreglo en paralelo es paralelizar, mapear y recopilar el arreglo.

RDD a partir de datos en almacenamiento confiable. Esto significa que los • para cada: pasa cada elemento a través de una función proporcionada
RDD siempre se pueden reconstruir si los nodos fallan. por el usuario. Esto solo se hace por los efectos secundarios de la
En Spark, cada RDD está representado por un objeto Scala. Spark función (que podría ser copiar datos a otro sistema o actualizar una
permite a los programadores construir RDD de cuatro maneras: variable compartida como se explica a continuación).

• A partir de unafileen un sistema de archivos compartido, como el Sistema Notamos que Spark actualmente no admite una operación de
de archivos distribuidos de Hadoop (HDFS). reducción agrupada como en MapReduce; Los resultados de
• Por“paralelizar”una colección de Scala (p. ej., una matriz) en reducción solo se recopilan en un proceso (el controlador).3
el programa del controlador, lo que significa dividirla en una Planeamos admitir reducciones agrupadas en el futuro usando una
serie de segmentos que se enviarán a varios nodos. transformación "shuffle" en conjuntos de datos distribuidos, como se
describe en la Sección 7. Sin embargo, incluso usar un solo reductor
• Portransformandoun RDD existente. Un conjunto de datos con
es suficiente para expresar una variedad de algoritmos útiles. Por
elementos de tipoAse puede transformar en un conjunto de
ejemplo, un artículo reciente sobre MapReduce para el aprendizaje
datos con elementos de tipoBusando una operación llamada
automático en sistemas multinúcleo [10] implementó diez algoritmos
FloridaenMapa, que pasa cada elemento a través de una función
de aprendizaje sin admitir la reducción paralela.
de tipo proporcionada por el usuarioA⇒Lista[B].1Otras
transformaciones se pueden expresar usandoFloridaenMapa, 2.3 Variables compartidas
incluidomapa (pasar elementos a través de una función de tipoA
Los programadores invocan operaciones comomapa,fifiltroyreducir
⇒B) yfifiltro(elegir elementos que coincidan con un predicado).
pasando cierres (funciones) a Spark. Como es típico en la
• Al cambiar elpersistenciade un RDD existente. Por defecto, los
programación funcional, estos cierres pueden referirse a variables en
RDD son perezosos y efímeros. Es decir, las particiones de un
el ámbito donde se crean. Normalmente, cuando Spark ejecuta un
conjunto de datos se materializan a pedido cuando se usan en
cierre en un nodo trabajador, estas variables se copian en el
una operación paralela (p. ej., al pasar un bloque de un archivo a
trabajador. Sin embargo, Spark también permite a los programadores
través de una función de mapa) y se descartan de la memoria
crear dos tipos restringidos devariables compartidaspara admitir dos
después de su uso.2Sin embargo, un usuario puede alterar la
patrones de uso simples pero comunes:
persistencia de un RDD a través de dos acciones:
• Variables de difusiónNota: si se utiliza una gran cantidad de
– ElcacheLa acción deja el conjunto de datos perezoso, pero
datos de solo lectura (p. ej., una tabla de búsqueda) en varias
sugiere que debe mantenerse en la memoria después de la
operaciones paralelas, es preferible distribuirla a los trabajadores
primera vez que se calcula, porque se reutilizará.
solo una vez en lugar de empaquetarla con cada cierre. Spark le
1mapa planotiene la misma semántica que elmapaen MapReduce, peromapa permite al programador crear una "variante de transmisión".
generalmente se usa para referirse a una función uno a uno de tipoA⇒Ben Scala.
2Así es como funcionan las “colecciones distribuidas” en DryadLINQ. 3Sin embargo, primero se realizan reducciones locales en cada nodo.

2
capaz” que envuelve el valor y asegura que solo se wsobre los datos para moverwen una dirección que lo mejore. Por lo tanto, se
copie a cada trabajador una vez. beneficia enormemente del almacenamiento en caché de los datos en la

• Acumuladores: Estas son variables que los trabajadores solo memoria a lo largo de las iteraciones. No explicamos la regresión logística en

pueden "agregar" usando una operación asociativa, y que solo el detalle, pero la usamos para mostrar algunas características nuevas de Spark.

controlador puede leer. Se pueden usar para implementar


// Leer puntos de un archivo de texto y almacenarlos en caché
contadores como en MapReduce y para proporcionar una val points = spark.textFile(...)
sintaxis más imperativa para sumas paralelas. Los acumuladores . mapa (punto de análisis). caché ()
se pueden definir para cualquier tipo que tenga una operación // Inicializar w a un vector D-dimensional aleatorio var w =
de "sumar" y un valor "cero". Debido a su semántica de "solo Vector.random(D)
agregar", son fáciles de hacer tolerantes a fallas. // Ejecutar múltiples iteraciones para actualizar w
para (i <- 1 a ITERACIONES) {
3 ejemplos val grad = chispa.acumulador(nuevo Vector(D)) para (p <-
Ahora mostramos algunos ejemplos de programas Spark. Tenga en cuenta que puntos) { // Se ejecuta en paralelo
omitimos los tipos de variables porque Scala admite la inferencia de tipos.
val s = (1/(1+exp(-py*(w dot px)))-1)*py grad += s * px

3.1 Búsqueda de texto }


Supongamos que deseamos contar las líneas que contienen errores en un archivo de
w -= grad.value
registro grande almacenado en HDFS. Esto se puede implementar comenzando con un
}
objeto de conjunto de datos de archivo de la siguiente manera:
Primero, aunque creamos un RDD llamadopuntos,lo
procesamos ejecutando unparabucle sobre él. Elparallave-
archivo val = chispa.textFile("hdfs://...")
val errs = archivo.filtro(_.contains("ERROR"))palabra en Scala es azúcar sintáctico para invocar elpara cada
val unos = errs.map(_ => 1) val cuenta método de una colección con el cuerpo del bucle como cierre. Es
= unos.reduce(_+_) decir, el códigopara (p <- puntos){cuerpo}es equivalente
alente apuntos.foreach(p =>{cuerpo}). Por lo tanto,
Primero creamos un conjunto de datos distribuido llamadoarchivo estamos invocando el paralelo de Sparkpara cadaoperación.
que representa el archivo HDFS como una colección de líneas. En segundo lugar, para resumir el gradiente, usamos una variable
Transformamos este conjunto de datos para crear el conjunto de acumuladora llamadadegradado (con un valor de tipoV ector). Tenga en
líneas que contienen "ER-ROR" (errar),y luego asigne cada línea a un 1 cuenta que el bucle se suma adegradadoutilizando un sobrecargado
y sume estos usandoreducir. Los argumentos afifiltro,mapay reducir + =operador. La combinación de acumuladores ypara
son sintaxis de Scala para literales de función. La sintaxis permite que los programas Spark se parezcan mucho a los
Tenga en cuenta quese equivocayunosson RDD perezosos que nunca se programas seriales imperativos. De hecho, este ejemplo difiere de
materializan. En cambio, cuandoreducirse llama, cada nodo de trabajo una versión en serie de regresión logística en solo tres líneas.
escanea bloques de entrada en forma de transmisión para evaluar
3.3 Mínimos cuadrados alternos
unos,los agrega para realizar una reducción local y envía su recuento
local al controlador. Cuando se usa con conjuntos de datos perezosos Nuestro ejemplo final es un algoritmo llamado mínimos cuadrados

de esta manera, Spark emula de cerca a MapReduce. alternos (ALS). ALS se usa para problemas de filtrado colaborativo, como

Donde Spark difiere de otros marcos es que puede hacer que predecir las calificaciones de los usuarios para películas que no han visto

algunos de los conjuntos de datos intermedios persistan entre en función de su historial de calificación de películas (como en Netflix

operaciones. Por ejemplo, si quisiera reutilizar else equivoca Challenge). A diferencia de nuestros ejemplos anteriores, ALS requiere un

conjunto de datos, podríamos crear un RDD en caché a partir de él de la siguiente manera:


uso intensivo de la CPU en lugar de un uso intensivo de los datos.
Esbozamos brevemente ALS y remitimos al lector a [27] para obtener
val cachedErrs = errs.cache() más detalles. Supongamos que quisiéramos predecir las calificaciones detu
usuarios parametropelículas, y que teníamos una matriz parcialmente llena
Ahora seríamos capaces de invocar operaciones paralelas en Rque contiene las calificaciones conocidas para algunos pares de películas
cachedErrso en conjuntos de datos derivados de él como de costumbre,
de usuario. modelos ALSRcomo el producto de dos matricesMETRO ytude
pero los nodos almacenarían en caché particiones decachedErrsen la
dimensionesmetro×kyk×turespectivamente; es decir, cada usuario y cada
memoria después de la primera vez que los calculan, lo que acelera
película tiene unak"vector de funciones" bidimensional que describe sus
enormemente las operaciones posteriores en él.
características, y la calificación de un usuario para una película es el
3.2 Regresión logística producto escalar de su vector de funciones y el de la película. ALS resuelve
paraMETROytuusando las calificaciones conocidas y luego calculaMETRO×
El siguiente programa implementa la regresión logística [3], un
tupara predecir las desconocidas. Esto se hace usando el siguiente proceso
algoritmo de clasificación iterativo que intenta encontrar un
iterativo:
hiperplanowque separa mejor dos conjuntos de puntos. El
algoritmo realiza un descenso de gradiente: comienzawen un 1. InicializarMETROa un valor aleatorio.

valor aleatorio, y en cada iteración, suma una función de 2. OptimizartudadoMETROpara minimizar el error enR.

3
3. OptimizarMETROdadotupara minimizar el error enR. HdfsTextFile
archivo:
4. Repita los pasos 2 y 3 hasta la convergencia. ruta = hdfs://…

ALS se puede paralelizar actualizando diferentes usuarios/películas


Conjunto de datos filtrados
en cada nodo en los pasos 2 y 3. Sin embargo, debido a que todos los errores:
func = _. contiene (…)
pasos usanR, es útil hacerRuna variable de difusión para que no se
vuelva a enviar a cada nodo en cada paso. A continuación se muestra
errores en caché: CachedDataset
una implementación de Spark de ALS que lo hace. Tenga en cuenta
que nosotrosparalelizarla colección0 hasta tu
MappedDataset
(un objeto de rango de Scala) yrecolectarpara actualizar cada matriz: unos:
función = _ => 1

val Rb = chispa.broadcast(R) para (i <-


Figura 1: Cadena de linaje para los objetos del conjunto de datos distribuidos
1 a ITERACIONES) {
definidos en el ejemplo de la Sección 4.
U = chispa.paralelizar (0 hasta u)
. map(j => actualizarUsuario(j, Rb, M))
. recolectar() tarea a una de sus ubicaciones preferidas usando una técnica llamada
M = chispa.paralelizar (0 hasta m) programación de retraso [26]. Una vez lanzada en un trabajador, cada
. map(j => actualizarUsuario(j, Rb, U)) tarea llamagetIteratorpara comenzar a leer su partición.
. recolectar() Los diferentes tipos de RDD difieren solo en cómo implementan la
} interfaz de RDD. Por ejemplo, para unHdfs-TextFile, las particiones
son ID de bloque en HDFS, sus ubicaciones preferidas son las
4 Implementación ubicaciones de bloque ygetIterator abre una secuencia para leer un

Spark se basa en Mesos [16, 15], un "sistema operativo de clúster" bloque. en unMappedDataset, las particiones y las ubicaciones

que permite que varias aplicaciones paralelas compartan un clúster preferidas son las mismas que para el padre, pero el iterador aplica la

de manera detallada y proporciona una API para que las aplicaciones función de mapa a los elementos del padre. Finalmente, en un

inicien tareas en un clúster. Esto permite que Spark se ejecute junto CachedDataset, el getIteratorEl método busca una copia en caché
con los marcos de computación en clúster existentes, como los local de una partición transformada, y las ubicaciones preferidas de

puertos Mesos de Hadoop y MPI, y comparta datos con ellos. Además, cada partición comienzan igual que las ubicaciones preferidas de los

construir sobre Mesos redujo en gran medida el esfuerzo de padres, pero se actualizan después de que la partición se almacena

programación que tuvo que realizar Spark. en caché en algún nodo para preferir reutilizar ese nodo. Este diseño

El núcleo de Spark es la implementación de conjuntos de datos hace que las fallas sean fáciles de manejar: si un nodo falla, sus

distribuidos resilientes. Como ejemplo, supongamos que definimos un particiones se vuelven a leer desde sus conjuntos de datos principales

conjunto de datos en caché llamadocachedErrsque representan mensajes y finalmente se almacenan en caché en otros nodos.

de error en un archivo de registro, y que contamos sus elementos usando Por último, enviar tareas a los trabajadores requiere que se les envíen

mapayreducir, como en la Sección 3.1: cierres, tanto los cierres que se usan para definir un conjunto de datos
distribuido como los cierres que se transfieren a operaciones como reducir.
archivo val = chispa.textFile("hdfs://...") Para lograr esto, nos basamos en el hecho de que Scala Clo-
val errs = archivo.filtro(_.contains("ERROR"))Los seguros son objetos de Java y se pueden serializar utilizando el software de Java.
val cachedErrs = errs.cache() val ones = rialización; esta es una característica de Scala que hace que sea
cachedErrs.map(_ => 1) val count = relativamente sencillo enviar un cálculo a otra máquina. Sin embargo,
ones.reduce(_+_) la implementación de cierre incorporada de Scala no es ideal, porque
hemos encontrado casos en los que un objeto de cierre
Estos conjuntos de datos se almacenarán como una cadena de objetos cap-
hace referencia a variables en el ámbito externo del cierre que no se
girando ellinajede cada RDD, que se muestra en la Figura 1. Cada
utilizan realmente en su cuerpo. Hemos presentado un informe de
objeto de conjunto de datos contiene un puntero a su padre e
error sobre esto, pero mientras tanto, hemos resuelto el problema
información sobre cómo se transformó el padre.
realizando un análisis estático de byte de clases de cierre.
Internamente, cada objeto RDD implementa la misma
código para detectar estas variables no utilizadas y establecer los
interfaz simple, que consta de tres operaciones:
campos correspondientes en el objeto de cierre paranulo.omitimos
• obtenerparticiones, que devuelve una lista de ID de partición. los detalles de este análisis por falta de espacio.
• getIterator(partición), que itera sobre una partición. Variables compartidas:Los dos tipos de variables compartidas en
• getPreferredLocations(partición), que se utiliza para Spark, variables de difusión y acumuladores, se implementan
programación de tareas para lograr la localidad de datos. Mented usando clases con formatos de serialización personalizados.
Cuando se invoca una operación paralela en un conjunto de datos, Spark Cuando uno crea una variable de difusiónbcon un valorv,
crea untareapara procesar cada partición del conjunto de datos y vse guarda en un archivo en un sistema de archivos compartido. La forma
envía estas tareas a los nodos trabajadores. Tratamos de enviar cada serializada debes una ruta a este archivo. Cuandobse consulta el valor

4
en un nodo trabajador, Spark primero verifica sivestá en un caché 4000

Tiempo de ejecución (s)


local y lo lee desde el sistema de archivos si no lo está. Inicialmente
3000
usamos HDFS para transmitir variables, pero estamos desarrollando
un sistema de transmisión de transmisión más eficiente. 2000 Hadoop
Los acumuladores se implementan utilizando un "truco de 1000 Chispa - chispear

serialización" diferente. Cada acumulador recibe una identificación


0
única cuando se crea. Cuando se guarda el acumulador, su forma
1 5 10 20 30
serializada contiene su ID y el valor "cero" para su tipo. En los
Número de iteraciones
trabajadores, se crea una copia separada del acumulador para cada
subproceso que ejecuta una tarea utilizando variables locales del
subproceso y se restablece a cero cuando comienza una tarea. Figura 2: rendimiento de la regresión logística en Hadoop y Spark.

Después de que se ejecuta cada tarea, el trabajador envía un mensaje


al programa controlador que contiene las actualizaciones que realizó las iteraciones toman solo 6 segundos, cada una porque reutilizan los datos almacenados en

en varios acumuladores. El controlador aplica actualizaciones de cada caché. Esto permite que el trabajo se ejecute hasta 10 veces más rápido.

partición de cada operación solo una vez para evitar el doble conteo También hemos intentado bloquear un nodo mientras se ejecutaba el
cuando las tareas se vuelven a ejecutar debido a fallas. trabajo. En el caso de 10 iteraciones, esto ralentiza el trabajo en 50

Integración del intérprete:Por falta de espacio, solo segundos (21 %) en promedio. Las particiones de datos en el nodo perdido

esbozamos cómo hemos integrado Spark en el intérprete de se vuelven a calcular y se almacenan en caché en paralelo en otros nodos,

Scala. El intérprete de Scala normalmente opera compilando pero el tiempo de recuperación fue bastante alto en el experimento actual

una clase para cada línea escrita por el usuario. Esta clase porque usamos un tamaño de bloque HDFS alto (128 MB), por lo que solo

incluye un objeto singleton que contiene las variables o había 12 bloques por nodo y el proceso de recuperación no pudo utilizar

funciones en esa línea y ejecuta el código de la línea en su todos los núcleos del clúster. Los tamaños de bloque más pequeños

constructor. Por ejemplo, si el usuario escribevar x = 5seguido producirían tiempos de recuperación más rápidos.

porimprimir(x),el intérprete define una clase (digamos Mínimos cuadrados alternos:Hemos implementado el trabajo de
Línea 1)que contieneXy hace que la segunda línea se com- mínimos cuadrados alternos en la Sección 3.3 para medir el beneficio
apilar aprintln(Línea1.getInstance().x).Estos de las variables de difusión para trabajos iterativos que copian un
las clases se cargan en la JVM para ejecutar cada línea. Para que conjunto de datos compartido en múltiples nodos. Encontramos que
el intérprete funcione con Spark, hicimos dos cambios: sin usar variables de transmisión, el tiempo para reenviar la matriz de
1. Hicimos que el intérprete envíe las clases que define a un sistema de calificacionesRen cada iteración dominaba el tiempo de ejecución del
archivos compartido, desde el cual los trabajadores pueden cargarlas trabajo. Además, con una implementación ingenua de transmisión
utilizando un cargador de clases Java personalizado. (usando HDFS o NFS), el tiempo de transmisión creció linealmente con
2. Cambiamos el código generado para que el objeto singleton de la cantidad de nodos, lo que limita la escalabilidad del trabajo.
cada línea haga referencia directamente a los objetos singleton Implementamos un sistema de multidifusión a nivel de aplicación
de las líneas anteriores, en lugar de pasar por el código estático. para mitigar esto. Sin embargo, incluso con transmisión rápida,
obtener Instanciamétodos. Esto permite que los cierres capturen reenviarRen cada iteración es costoso. almacenamiento en cachéR en
el estado actual de los singletons a los que hacen referencia cada la memoria de los trabajadores que usan una variable de transmisión
vez que se serializan para enviarlos a un trabajador. Si no mejoró el rendimiento en 2,8 veces en un experimento con 5000
hubiéramos hecho esto, entonces se actualiza a los objetos películas y 15000 usuarios en un clúster EC2 de 30 nodos.
singleton (por ejemplo, una configuración de líneax = 7en el
Chispa interactiva:Usamos el intérprete de Spark para cargar
ejemplo anterior) no se propagaría a los trabajadores.
un volcado de Wikipedia de 39 GB en la memoria en 15
5 resultados máquinas EC2 “m1.xlarge” y consultarlo de forma interactiva. La
es
primera vez que los datos consultado, se tarda aproximadamente 35
Aunque nuestra implementación de Spark aún se encuentra en una etapa
onds, comparable t o rusegundos en ejecutar un trabajo de Hadoop. Cómo-
temprana, relacionamos los resultados de tres experimentos que muestran
nunca, posterior qu eries tomar sólo 0,5 a 1 segundo, incluso
su promesa como marco de computación en clúster.
si escanean todo el d ata.Esto proporciona una diferencia
Regresión logística:Comparamos el rendimiento de fer entexperiencia omp cualitativa al trabajo con datos locales.
el trabajo de regresión logística en la Sección 3.2 a una
implementación de regresión logística para Hadoop, utilizando un
6 Trabajo relacionado

conjunto de datos de 29 GB en 20 nodos EC2 "m1.xlarge" con 4 di stribShar usado mi d Memoria:El resistente dis-
adoo
núcleos cada uno. Los resultados se muestran en la Figura 2.durazno
Con H tributed n ser visto como una tracción para dis-
conjuntos de datos ca abdominales

la iteración tarda 127 s, porque se ejecuta como un pendiente


independiente tributed memoria compartida ory (DSM), que se ha estudiado s
trabajo de MapReduce. con chispa , el primera iteración n tomar es 174s extensión muy [20]. R DDdifieren de las interfaces DSM en
(probablemente debido al uso de Scala ins té de Java), pero t sub consecuente dosAy sí. Primero, R. DD Provide un mucho más restringido

5
modelo de programación, pero uno que permite que los conjuntos de tists que permite a los usuarios iniciar cálculos en un clúster utilizando una
datos se reconstruyan de manera eficiente si fallan los nodos del clúster. interfaz de cola de tareas tolerante a fallas o una interfaz de paso de
Mientras que algunos sistemas DSM logran tolerancia a fallas a través de mensajes de bajo nivel. Spark proporciona una interfaz interactiva similar,
puntos de control [18], Spark reconstruye particiones perdidas de RDD pero se enfoca en cálculos intensivos en datos.
usando información de linaje capturada en los objetos RDD. Esto significa
Linaje:La captura de información de linaje o procedencia para conjuntos de
que solo es necesario volver a calcular las particiones perdidas, y que se
datos ha sido durante mucho tiempo un tema de investigación en los
pueden volver a calcular en paralelo en diferentes nodos, sin necesidad de
campos de bases de datos y computación científica, para aplicaciones tales
que el programa vuelva a un punto de control. Además, no hay gastos
como explicar resultados, permitir que otros los reproduzcan y volver a
generales si no falla ningún nodo. En segundo lugar, los RDD impulsan el
calcular datos si se encuentra un error en un paso de flujo de trabajo o si
cálculo a los datos como en MapReduce [11], en lugar de permitir que los
se pierde un conjunto de datos. Remitimos al lector a [7], [23] y [9] para
nodos arbitrarios accedan a un espacio de direcciones global.
una revisión de este trabajo. Spark proporciona un modelo de
Otros sistemas también han restringido el modelo de
programación paralelo restringido donde el linaje detallado es económico
programación DSM para mejorar el rendimiento, la confiabilidad y la
de capturar, de modo que esta información se puede usar para volver a
programabilidad. Munin [8] permite a los programadores anotar
calcular los elementos perdidos del conjunto de datos.
variables con el patrón de acceso que tendrán para elegir un
protocolo de consistencia óptimo para ellas. Linda [13] proporciona 7 Discusión y trabajo futuro
un modelo de programación espacial de tuplas que puede
implementarse con tolerancia a fallas. Thor [19] proporciona una Spark proporciona tres abstracciones de datos simples para la

interfaz para objetos compartidos persistentes. programación de clústeres: conjuntos de datos distribuidos resistentes
(RDD) y dos tipos restringidos de variables compartidas: variables de
Marcos de computación en clúster:Las operaciones paralelas de transmisión y acumuladores. Si bien estas abstracciones son limitadas,
Spark encajan en el modelo MapReduce [11]. Sin embargo, hemos descubierto que son lo suficientemente potentes como para
operan en RDD que pueden persistiral otro lado deoperaciones. expresar varias aplicaciones que plantean desafíos para los marcos de
Twister [6, 12], un marco de MapReduce que permite que las computación en clúster existentes, incluidos los cálculos iterativos e
tareas de mapas de larga duración mantengan datos estáticos en la interactivos. Además, creemos que la idea central detrás de los RDD, de un
memoria entre trabajos, también reconoció la necesidad de ampliar identificador de conjunto de datos que tiene suficiente información para
MapReduce para admitir trabajos iterativos. Sin embargo, Twister (re)construir el conjunto de datos a partir de datos disponibles en un
actualmente no implementa tolerancia a fallas. La abstracción de almacenamiento confiable, puede resultar útil para desarrollar otras
Spark de conjuntos de datos distribuidos resilientes es tolerante a abstracciones para programar clústeres.
fallas y más general que MapReduce iterativo. Un programa Spark
En el trabajo futuro, planeamos centrarnos en cuatro áreas:
puede definir múltiples RDD y alternar entre ejecutar operaciones en
1. Caracterizar formalmente las propiedades de los RDD y
ellos, mientras que un programa Twister tiene solo una función de
otras abstracciones de Spark, y su idoneidad para varias
mapa y una función de reducción. Esto también hace que Spark sea
clases de aplicaciones y cargas de trabajo.
útil para el análisis de datos interactivo, donde un usuario puede
definir varios conjuntos de datos y luego consultarlos. 2. Mejorar la abstracción de RDD para permitir a los programadores

Las variables de transmisión de Spark brindan una función similar a la intercambiar entre el costo de almacenamiento y el costo de reconstrucción.

caché distribuida de Hadoop [2], que puede distribuir un archivo a todos 3. Definir nuevas operaciones para transformar los RDD, incluida una
los nodos que ejecutan un trabajo en particular. Sin embargo, las variables operación de "reproducción aleatoria" que reparte un RDD por
de difusión se pueden reutilizaral otro lado deoperaciones paralelas. una clave determinada. Tal operación nos permitiría
implementar group-bys y joins.
Integración de idiomas:La integración del lenguaje de Spark es similar
a la de DryadLINQ [25], que utiliza el soporte de .NET para consultas 4. Proporcione interfaces interactivas de nivel superior
integradas del lenguaje para capturar un árbol de expresión que además del intérprete de Spark, como SQL y R [4] shells.
define una consulta y ejecutarlo en un clúster. A diferencia de
8 Agradecimientos
DryadLINQ, Spark permite que los RDD persistan en la memoria en
operaciones paralelas. Además, Spark enriquece el modelo de Agradecemos a Ali Ghodsi por sus comentarios sobre este
integración de idiomas al admitir variables compartidas (variables de documento. Esta investigación fue apoyada por California
transmisión y acumuladores), implementadas mediante clases con MICRO, California Discovery, el Consejo de Investigación de
formularios serializados personalizados. Ingeniería y Ciencias Naturales de Canadá, así como los
Nos inspiramos para usar Scala para la integración de lenguajes siguientes patrocinadores de Berkeley RAD Lab: Sun
por SMR [14], una interfaz de Scala para Hadoop que usa cierres para Microsystems, Google, Microsoft, Amazon, Cisco, Cloudera, eBay,
definir mapas y reducir tareas. Nuestras contribuciones sobre SMR Facebook, Fujitsu, HP, Intel, NetApp, SAP, VMware y Yahoo!.
son variables compartidas y una implementación más robusta de
serialización de cierre (descrito en la Sección 4).
Referencias
Finalmente, IPython [22] es un intérprete de Python para la ciencia. [1] Colmena Apache. http://hadoop.apache.org/hive.

6
[2] Tutorial de Hadoop Map/Reduce. http://hadoop.apache.org/ Procesando. EnSIGMOD '08. ACM, 2008.
common/docs/r0.20.0/mapred tutorial.html. [22] F. Pérez y BE Granger. IPython: un sistema para
[3] Regresión logística – Wikipedia. http:// computación científica interactiva.computar ciencia Ing.,
en.wikipedia.org/wiki/Regresión logística. 9(3):21–29, mayo de 2007.
[4] El proyecto R para computación estadística. [23] YL Simmhan, B. Plale y D. Gannon. Una encuesta sobre la
http://www.r-project.org. procedencia de los datos en e-ciencia.Rec. SIGMOD.,
[5] Lenguaje de programación Scala. http://www.scala-lang.org. 34(3):31–36, 2005.
[6] Twister: MapReduce iterativo. [24] H.-c. Yang, A. Dasdan, R.-L. Hsiao y DS Parker. Map-reduce-
http://iterativemapreduce.org. merge: procesamiento de datos relacionales simplificado en
[7] R. Bose y J. Frew. Recuperación de linaje para el procesamiento de datos grandes clústeres. EnSIGMOD '07, páginas 1029–1040. ACM,
científicos: una encuesta.Encuestas informáticas de ACM, 37:1–28, 2005. 2007.
[25] Y. Yu, M. Isard, D. Fetterly, M. Budiu, Ú. Erlingson,
[8] JB Carter, JK Bennett y W. Zwaenepoel. PK Gunda y J. Currey. DryadLINQ: un sistema para computación
Implementación y ejecución de Munin. EnSOSP '91. paralela de datos distribuidos de propósito general que utiliza un
ACM, 1991. lenguaje de alto nivel. EnOSDI '08, San Diego, CA, 2008.
[9] J. Cheney, L. Chiticariu y W.-C. Broncearse. Procedencia en bases de [26] M. Zaharia, D. Borthakur, J. Sen Sarma, K. Elmeleegy,
datos: por qué, cómo y dónde.Fundamentos y Tendencias en Bases S. Shenker y I. Stoica. Programación diferida: una técnica
de Datos, 1(4):379–474, 2009. simple para lograr localidad y equidad en la programación
[10] CT Chu, SK Kim, YA Lin, Y. Yu, GR Bradski, de grupos. EnEuroSys 2010, abril de 2010.
AY Ng y K. Olukotun. Map-reduce para aprendizaje automático en [27] Y. Zhou, D. Wilkinson, R. Schreiber y R. Pan. Filtrado
multinúcleo. EnPINZAS '06, páginas 281–288. Prensa del MIT, 2006. colaborativo paralelo a gran escala para el premio Netflix.
EnAAIM'08, páginas 337–348, Berlín, Heidelberg, 2008.
[11] J. Dean y S. Ghemawat. MapReduce: Procesamiento de datos Springer-Verlag.
simplificado en grandes clústeres.común MCA, 51(1):107–
113, 2008.
[12] J. Ekanayake, S. Pallickara y G. Fox. MapReduce para análisis
científicos intensivos en datos. EnESCIENCIA '08, páginas 277–
284, Washington, DC, EE. UU., 2008. IEEE Computer Society.

[13] D. Gelernter. Comunicación generativa en linda.ACM


Trans. Programa. Idioma sist., 7(1):80–112, 1985.
[14] D. Pasillo. Un lenguaje escalable y un marco escalable.
http://www.scala-blogs.org/2008/09/scalable-
languageand-scalable.html.
[15] B. Hindman, A. Konwinski, M. Zaharia, A. Ghodsi, AD Joseph, RH
Katz, S. Shenker e I. Stoica. Mesos: una plataforma para
compartir recursos de granularidad fina en el centro de datos.
Informe técnico UCB/EECS-2010-87, Departamento de EECS,
Universidad de California, Berkeley, mayo de 2010.

[16] B. Hindman, A. Konwinski, M. Zaharia e I. Stoica. Un sustrato


común para la computación en clúster. EnTaller sobre Temas
Candentes en Computación en la Nube (HotCloud) 2009, 2009.
[17] M. Isard, M. Budiu, Y. Yu, A. Birrell y D. Fetterly. Dryad: Programas
paralelos de datos distribuidos a partir de bloques de construcción
secuenciales. EnEuroSys 2007, páginas 59–72, 2007.
[18] A.-M. Kermarrec, G. Cabillic, A. Gefflaut, C. Morin y
I. Puau. Una memoria compartida distribuida recuperable que integra
coherencia y capacidad de recuperación. EnFTCS '95. Sociedad de
Computación IEEE, 1995.
[19] B. Liskov, A. Adya, M. Castro, S. Ghemawat, R. Gruber,
U. Maheshwari, AC Myers, M. Day y L. Shrira. Uso compartido
seguro y eficiente de objetos persistentes en thor. En SIGMOD
'96, páginas 318–329. ACM, 1996.
[20] B. Nitzberg y V. Lo. Memoria compartida distribuida: una encuesta de
problemas y algoritmos.Computadora, 24(8):52-60, agosto de 1991.

[21] C. Olston, B. Reed, U. Srivastava, R. Kumar y


A. Tomkins. Pig latin: un idioma no tan extranjero para los datos

También podría gustarte