Grandes ahorros en Big Data

Kevin Jevin Woo
Lyft Engineering en Español
9 min readOct 4, 2023

Cómo la plataforma de aprendizaje automático de Lyft ahorra tiempo y dinero en cargas de trabajo de Big Data/aprendizaje automático

Este artículo fue publicado originalmente el 11 de abril de 2023 en eng.lyft.com y fue traducido por Kevin Woo.

Imagen por DALL·E

Motivación

En artículos anteriores, hablamos sobre la plataforma de aprendizaje automático de Lyft, LyftLearn, que gestiona el entrenamiento de modelos de aprendizaje automático y las predicciones por lotes. Con la cantidad de datos que Lyft tiene que procesar, es natural que el costo de operar la plataforma sea muy alto.

Cuando hablamos sobre cómo democratizamos el cómputo distribuido, describimos una solución con algunos principios de diseño clave como iteraciones rápidas, facilidad de uso y aplicación de buenas prácticas.

A principios de 2022 completamos esta migración. Ahora es un buen momento para evaluar el impacto de las decisiones de diseño en los últimos dos años, tanto en el aumento de la productividad de los desarrolladores como en la reducción de costos.

Métricas Principales

En este artículo, definimos cada ejecución como la ejecución de una tarea de datos/aprendizaje automático utilizando un clúster efímero de Spark/Ray. El tiempo y el costo de las ejecuciones se miden por su uso efímero de Spark/Ray.

Las ejecuciones son la forma de utilizar el sistema de datos grandes de LyftLearn tanto en el entorno de desarrollo como en el de producción. Hay dos casos de uso principales en el entorno de desarrollo: ejecutar tareas ad-hoc e iterar para crear un flujo de trabajo de producción.

Compararemos las métricas de las ejecuciones ("runs") entre 2021 y 2022 en desarrollo (dev) y producción (prod).

Productividad

En 2022, tuvimos un gran aumento en el uso de producción.

Número total de ejecuciones (%) en proudcción y en desarollo

El número total de ejecuciones aumentó un 286%, y las ejecuciones de producción aumentaron un 424%. En secciones posteriores, explicaremos por qué el aumento no es proporcional entre el entorno de desarrollo y el de producción.

También aceleramos la velocidad de desarrollo de los usuarios:

Comparación promedio de minutos requerido por ejecución en desarrollo vs producción

El tiempo promedio por iteración (las barras azules) en datos masivos se redujo de 31 minutos a 11 minutos. Esto muestra que los ingenieros de ML de Lyft pueden iterar en problemas grandes a una velocidad 3 veces mayor en comparación con 2021.

Observa que el tiempo de ejecución de producción aumentó ligeramente debido a nuevos trabajos más pesados. Esto también indica que el gran aumento en las ejecuciones de producción es orgánico y no se debe a la división de cargas de trabajo existentes.

Costo

Un mayor uso y iteraciones más rápidas en datos masivos suelen requerir más recursos de cómputo y costos más altos. ¿Cuánto gastamos en 2022 en comparación con 2021?

Comparación de costos de producción y desarrollo

Sorprendentemente, en 2022, no solo logramos controlar el costo general (+6%), sino que también logramos llevar una parte significativa del esfuerzo de desarrollo a producción.

El costo total de desarrollo se redujo un 32% a pesar de que el uso de desarrollo aumentó ligeramente en 2022. ¿Cómo lo logramos?

Costos por ejecución en los últimos 2 años en desarrollo y producción

Pudimos reducir el costo promedio del ambiente de desarrollo por ejecución de $25 a $10.7 (-57%). Esto significa que los profesionales de ML de Lyft pueden iterar en problemas grandes a la mitad del costo en comparación con 2021.

Otro dato que vale la pena mencionar: el costo total de AWS de LyftLearn se redujo un 6% en 2022 en comparación con 2021.

Reducción de los costos de computación

En el artículo anterior (en inglés), mencionamos que la plataforma de LyftLearn impone clústeres efímeros. En la experiencia de notebook de LyftLearn, los usuarios pueden declarar los recursos del clúster para cada paso en su flujo de trabajo. En la siguiente imagen, un usuario está solicitando un clúster de Spark con 8 máquinas, cada una con 8 CPUs y 32 GB de RAM. El clúster es efímero y solo existe durante la duración de la consulta de SparkSQL.

Definiendo configuración del clúster de Spark

Clústeres Efímeros y Estáticos

El uso de clústeres efímeros ha contribuido a una parte significativa de los ahorros totales. Plataformas gestionadas como AWS Elastic MapReduce tienden a requerir que un científico de datos inicie un clúster y luego desarrolle sobre ese clúster. Esto conduce a una sub-utilización (debido al tiempo de inactividad) durante la iteración del proyecto. Los clústeres efímeros aseguran que los usuarios asignen recursos costosos solo cuando sea necesario.

También es importante mencionar que LyftLearn desalienta la escalabilidad automática de Spark. La escalabilidad automática puede llevar a la inestabilidad o sub-utilización. Es menos útil cuando los clústeres ya son efímeros. También encontramos patrones similares discutidos en este artículo publicado por Sync Computing (en inglés).

Los beneficios de ser explícito en los recursos de cómputo son:

  1. Los usuarios son conscientes de los recursos que realmente necesitan para sus casos.
  2. Se reduce la contención de recursos en los clústeres de K8s.

A muchos usuarios de LyftLearn les sorprende el tiempo de inicio (2–5 segundos) debido a Kubernetes Spark con imágenes en caché. Los clústeres efímeros también reducen directamente el mantenimiento porque se pueden ejecutar diferentes pasos de un flujo de trabajo utilizando diferentes imágenes para separar paquetes que entran en conflicto entre sí (por ejemplo, que requieren diferentes versiones de dependencias).

Elecciones óptimas de herramientas

Otra gran parte de los ahorros de costos es elegir la herramienta más efectiva para el trabajo. Esto es evidente con Presto y Hive. En este artículo, compartimos las mejores prácticas para elegirlos:

Presto es bueno para escenarios de agregación y con una salida pequeña, no debería llevar más de 10 minutos. Si Presto es lento, prueba con Hive.

Hive es más lento pero generalmente más escalable. Siempre intenta guardar la salida en archivos en lugar de meterlas en Pandas.

A medida que aparecen más frameworks de trabajo de big data en el panorama de la ciencia de datos, debemos elegir la mejor herramienta para cada parte del trabajo. Una de las piezas importantes de la plataforma LyftLearn es brindar a los ingenieros de datos la flexibilidad y simplicidad para elegir la mejor herramienta para cada trabajo.

Por ejemplo, algunas canalizaciones de datos dentro de Lyft aprovechan Spark para el pre-procesamiento y Ray para la parte de aprendizaje automático distribuido. Esto también está habilitado específicamente por los clústeres efímeros. (Mira nuestra charla en Data AI Summit 2022)

Acelerando las iteraciones de desarrollo

Otra forma de ahorro menos rastreada son las horas ahorradas debido a las eficiencias operativas obtenidas gracias a la plataforma LyftLearn. La gran reducción en el tiempo de ejecución en desarrollo y la mayor proporción de ejecuciones en producción en comparación con el desarrollo se traduce directamente en que los científicos de datos tienen más tiempo para dedicarse al modelado y la computación científica. Más importante aún, más proyectos llegan a producción para generar un valor comercial real.

Nuestra capa de abstracción de cómputo, construida sobre el proyecto de código abierto Fugue, juega un papel clave en acelerar las iteraciones de desarrollo. Optimiza los flujos de trabajo de big data de tres formas:

Localización del desarrollo

Con un diseño agnóstico respecto al backend, podemos desarrollar lógica de computación distribuida (SQL o Python) en el backend local sin necesidad de un clúster. Solo el código bien probado se ejecuta en clústeres. Esto explica por qué en 2022 el aumento de ejecuciones en producción y desarrollo no fue proporcional. Gran parte de las iteraciones se realizaron localmente sin utilizar clústeres.

Descomposición de flujos de trabajo grandes

Esta es una de las fuentes de ahorro más importantes de LyftLearn.

Desarrollar una consulta compleja de Hive (Spark) con cientos de líneas es uno de los mayores y más comunes desafíos para los ingenieros de ML de Lyft. Debido a la sintaxis de Expresiones de Tablas Comunes (CTE, por sus siglas en inglés), descomponer una consulta SQL en pequeñas sub-consultas para ejecutar no es práctico. Iterar en tales consultas requiere volver a ejecutar toda la consulta cada vez. En el peor caso, cuando una consulta compleja nunca termina, el ingeniero nunca podría saber la causa del problema. Reintentar es ineficiente y también incurre en un gran costo.

FugueSQL es un superconjunto de SQL tradicional con una sintaxis y características mejoradas: no requiere CTE. En su lugar, la sintaxis de asignación puede facilitar la descomposición y combinación de consultas SQL.

Uso de FugueSQL para romper y combinar consultas SQL complejas

En el ejemplo anterior, supongamos que la consulta original de Hive tiene problemas desconocidos. Podemos reescribirla en FugueSQL y descomponerla en varias partes para iterar. En la primera celda, YIELD FILE almacenará en un caché b en un archivo (guardado por Spark) y pondrá la referencia disponible para las celdas siguientes. En la segunda celda, podemos usar directamente b, que se cargará desde S3. Por último, también podemos imprimir el resultado para verificar. De esta manera, podemos solucionar rápidamente problemas. Más importante aún, con el almacenamiento en caché, las celdas finalizadas no necesitarán volver a ejecutarse en las siguientes iteraciones.

Cuando varias partes funcionan de principio a fin, simplemente las copiamos y pegamos juntas y eliminamos el YIELD. Observa que también agregamos un PERSIST a b porque se usará dos veces en los pasos siguientes. Esto le indica explícitamente a Spark que almacene en caché este resultado para evitar el recálculo.

FugueSQL debería generar resultados equivalentes a la consulta SQL original, pero tiene ventajas significativas:

  1. La división y conquista se vuelve posible para SQL, lo que acelera significativamente el tiempo de iteración en problemas complejos.
  2. El FugueSQL final suele ser más rápido que el SQL original (si almacenamos en caché explícitamente los pasos intermedios para evitar el recálculo).

También podemos reconstruir fácilmente la consulta SQL tradicional después de solucionar todos los problemas en las iteraciones. La parte más lenta y costosa siempre son las iteraciones de desarrollo, las cuales podemos mejorar utilizando el enfoque de Fugue.

Adopción incremental

No requerimos que los usuarios modernicen toda su carga de trabajo de una sola vez. En cambio, los alentamos a migrar de manera incremental con la refactorización necesaria.

Existen una gran cantidad de cargas de trabajo existentes escritas con herramientas de datos pequeños como Pandas y scikit-learn. En muchos casos, si un paso requiere mucho cómputo, los usuarios pueden refactorizar su código para separar la lógica de cómputo principal y luego usar una llamada de transformación de Fugue para distribuir la lógica.

Por lo tanto, la adopción incremental también es un proceso natural para que los usuarios adopten buenas prácticas de codificación y reescriban código de alta calidad que sea agnóstico a la escala y agnóstico al marco de trabajo (Spark, Ray, Fugue, etc.).

Conclusion

Las métricas mostradas de 2021 a 2022 condujeron tanto a un aumento en la productividad como a ahorros de costos, y ni siquiera incluyen los beneficios de las horas humanas ahorradas debido a la mayor velocidad de desarrollo. Las ganancias de Lyft también aumentaron gracias a los modelos de aprendizaje automático que pudieron llegar a producción con el apoyo de la plataforma LyftLearn.

Desarrollar proyectos de big data puede ser significativamente costoso en tiempo y dinero, pero LyftLearn logró reducir los costos al hacer cumplir las mejores prácticas, simplificar el modelo de programación y acelerar las iteraciones.

¡Como siempre, Lyft está contratando! Si tienes pasión por desarrollar sistemas de última generación, únete a nuestro equipo.

--

--