5 Mejores prácticas de Spark para Data Science

Zion Badash
Computación en la nube
Que desearía saber antes de comenzar mi proyecto

5 Mejores prácticas de Spark para Data Science

¿Por qué moverse a spark?

Aunque todos hablamos de Big Data, por lo general suele pasar un cierto tiempo hasta que te lo encuentras en tu trabajo. Para mí en Wix.com fue más rápido de lo que pensaba, tener más de 160 millones de usuarios genera una gran cantidad de datos— y con ello surge la necesidad de escalar nuestro procesamiento de datos.

Si bien hay otras opciones (Dask por ejemplo), nos decidimos por Spark por 2 razones principales — (1) Es el sistema de vanguardia actual y se usa frecuentemente para Big Data. (2) Teníamos la infraestructura necesaria para Spark.

Cómo escribir en PySpark para personas pandas

Lo más probable es que estés familiarizado con los pandas, y cuando digo familiarizado me refiero a que sean tu lengua materna :)

El titular de la siguiente charla lo dice todo — Administración de datos con PySpark para científicos de datos que conocen Pandas (Data Wrangling with PySpark for Data Scientists Who Know Pandas) y es genial.

Este será un muy buen momento para notar que conseguir la sintaxis correcta puede ser un buen punto de partida, pero hace falta mucho más para tener un proyecto PySpark exitoso. Hay que entender cómo funciona Spark.

Es difícil hacer que Spark funcione correctamente, pero cuando funciona, ¡funciona muy bien!

 

Spark en pocas palabras

  • Solo me hundiría hasta las rodillas aquí, pero recomiendo visitar el siguiente artículo y leer la explicación de MapReduce para una explicación más extensa. — La guía del autoestopista para manejar Big Data usando Spark (The Hitchhikers guide to handle Big Data using Spark) .

 

El concepto que queremos entender aquí es la escalabilidad horizontal (Horizontal Scaling).

Es más fácil comenzar con la escalabilidad vertical (Vertical Scaling). Si tenemos un código de pandas que funciona muy bien, pero con el tiempo el volumen de datos se vuelve demasiado extenso para él, podemos potencialmente movernos a una máquina con más memoria y esperar que funcione. Esto significa que todavía tenemos una máquina que maneja todos los datos al mismo tiempo: escalamos verticalmente.

 

Si, en cambio, decidimos usar MapReduce y dividir los datos en fragmentos y dejar que diferentes máquinas manejen cada fragmento, estamos escalando horizontalmente.

 

5 mejores prácticas de Spark

Estas son las 5 mejores prácticas de Spark que me ayudaron a reducir el tiempo de ejecución en 10 veces y escalar nuestro proyecto.

1 - Empieza con algo pequeño: muestrea los datos (data sampling)

Si queremos que el Big Data funcione, primero queremos ver que estamos yendo en la dirección correcta utilizando una pequeña parte de los datos. En mi proyecto tomé muestras del 10% de los datos y me aseguré de que las canalizaciones (pipelines) funcionaran correctamente. Esto me permitió usar la sección SQL en la interfaz de usuario de Spark y ver cómo los números crecían a lo largo de todo el flujo, sin esperar demasiado a que se ejecutara el proceso.

Según mi experiencia, si se alcanza el tiempo de ejecución deseado con la muestra pequeña, generalmente se puede escalar con bastante facilidad.

 2 - Comprender los conceptos básicos: tareas, particiones y núcleos

Esto es probablemente lo más importante de entender a la hora de trabajar con Spark:

1 partición se hace para 1 tarea que se ejecuta en 1 núcleo

 Has de ser siempre consciente del número de particiones que tienes - sigue la cantidad de tareas en cada etapa y combínalas con la cantidad correcta de núcleos en tu conexión Spark. Algunos consejos y reglas generales para ayudarte con el proceso (tienes que probar cada una en tu caso particular.):


  •   La proporción entre tareas y núcleos debe ser de 2 a 4 tareas por cada núcleo.


  •  El tamaño de cada partición debe ser de 200 MB a 400 MB, esto depende de la memoria de cada trabajador, ajústalo a tus necesidades.

3 – Depurando Spark (Spark debugging)

Spark funciona con evaluación diferida, lo que significa que espera hasta que se llama a una acción antes de ejecutar el gráfico de instrucciones de cálculo. Ejemplos de acciones son show(), count(),...

Esto hace que sea muy difícil entender dónde están los errores / lugares que necesitan optimización en nuestro código. Una práctica que me es de gran utilidad es dividir el código en secciones usando df.cache() y luego usando df.count() para obligar a Spark a calcular el df en cada sección.

Ahora, usando la interfaz de usuario de Spark, puedes ver el cálculo de cada sección y detectar los problemas. Es importante tener en cuenta que el hacer esto sin utilizar el muestreo que mencionamos en (1) probablemente resultará en un tiempo de ejecución muy largo que será difícil de depurar.

4 - encontrar y resolver la asimetría estadística (skewness)

Comencemos por definir la asimetría. Como mencionamos antes, nuestros datos se dividen en particiones y, a lo largo de las transformaciones, es probable que el tamaño de cada partición cambie. Esto puede crear una amplia variación de tamaño entre las particiones, lo que significa que tenemos una asimetría en nuestros datos.

 

Se puede encontrar la asimetría observando los detalles de la etapa en la interfaz de usuario de Spark y buscando una diferencia significativa entre el máximo y la mediana:

La gran variación (mediana = 3 s, máxima = 7,5 min) podría sugerir una asimetría en los datos.

Esto significa que tenemos algunas tareas que fueron significativamente más lentas que las demás.

¿Por qué es tan malo? Esto puede hacer que otras etapas esperen por estas pocas tareas y dejen a los núcleos esperando sin hacer nada.

Preferiblemente, si sabes de dónde proviene el sesgo, puedes abordarlo directamente y cambiar la partición. Si no tienes ninguna idea o no puedes resolverlo directamente, intenta lo siguiente:

Ajusta el ratio entre las tareas y los núcleos

Como hemos mencionado, al tener más tareas que núcleos, esperamos que mientras se ejecuta la tarea más larga, otros núcleos permanezcan ocupados con las otras tareas. Aunque esto es cierto, la proporción mencionada anteriormente (2-4: 1) realmente no puede abordar una variación tan grande entre la duración de las tareas. Podemos intentar aumentar la proporción a 10: 1 y ver si ayuda, pero podría haber otras desventajas en este enfoque.

Salar los datos (Data salting)

Salting es reparticionar los datos con una clave aleatoria para que las nuevas particiones estén equilibradas. Aquí hay un ejemplo de código para Pyspark usando Groupby, que es el sospechoso habitual de causar asimetría:

5 - Problemas con el código iterativo en Spark

Esto es complicado. Como hemos mencionado, Spark usa evaluación diferida (lazy evaluation), por lo que al ejecutar el código, solo crea un gráfico computacional, un DAG. Pero este método puede ser muy problemático cuando tienes un proceso iterativo, porque el DAG reabre la iteración anterior y se vuelve muy grande, muy muy grande. Esto puede ser demasiado grande para que el controlador lo guarde en la memoria. Este problema es difícil de localizar porque la aplicación está bloqueada, pero aparece en la interfaz de usuario de Spark como si no se estuviera ejecutando ningún trabajo (lo cual es cierto) durante mucho tiempo, hasta que el controlador finalmente falla. 

Este es actualmente un problema inherente al usar Spark y la solución que funcionó para mí fue usar df.checkpoint() / df.localCheckpoint() cada 5-6 iteraciones (encuentra tu número ideal experimentando un poco). La razón por la que esto funciona es que checkpoint() está rompiendo el linaje (lineage) y el DAG (diferente a cache()), está guardando los resultados y comenzando desde el nuevo punto de control. La desventaja es que si ocurrió algo malo, no tienes el DAG completo para recrear el df.

 

Resumen


Como he dicho antes, se necesita tiempo para aprender cómo lograr que Spark haga su magia, pero estas 5 prácticas realmente impulsaron mi proyecto hacia adelante y espolvorearon algo de la magia de Spark en mi código. 

Para concluir, esta es la publicación que estaba buscando (y no encontré) cuando comencé mi proyecto. Espero que tú la hayas encontrado justo a tiempo.

 Referencias



Traducido por Mireia Kesti Izquierdo

 

Zion Badash

Data Scientist at Wix.com

Related Posts

Únete a nuestra Newsletter

Lidera la Conversación en la Nube