memory management - por - ¿Cómo lidiar con la memoria del ejecutor y la memoria del controlador en Spark?
memoria fiscal llena (2)
Estoy confundido acerca de lidiar con la memoria del ejecutor y la memoria del controlador en Spark.
La configuración de mi entorno es la siguiente:
- Memoria 128 G, 16 CPU para 9 VM
- Centos
- Hadoop 2.5.0-cdh5.2.0
- Spark 1.1.0
Información de datos de entrada:
- Archivo de datos de 3,5 GB de HDFS
Para el desarrollo simple, ejecuté mi código de Python en modo de clúster independiente (8 trabajadores, 20 núcleos, 45.3 G de memoria) con spark-submit
. Ahora me gustaría establecer la memoria del ejecutor o la memoria del controlador para la optimización del rendimiento.
De la documentación de Spark , la definición de memoria de ejecutor es
Cantidad de memoria que se utiliza por proceso de ejecución, en el mismo formato que las cadenas de memoria JVM (por ejemplo, 512 m, 2 g).
¿Qué hay de la memoria del controlador?
En una aplicación Spark, Driver es responsable de la programación de tareas y Executor es responsable de ejecutar las tareas concretas en su trabajo.
Si está familiarizado con MapReduce, sus tareas de mapa y tareas de reducción se ejecutan en Executor (en Spark, se llaman ShuffleMapTasks & ResultTasks), y también, cualquier RDD que quiera almacenar en caché también está en el montón y disco de la JVM del ejecutor.
Así que creo que unos pocos GB estarán bien para tu Driver.
La memoria que necesita asignar al controlador depende del trabajo.
Si el trabajo se basa exclusivamente en transformaciones y finaliza en alguna acción de salida distribuida como rdd.saveAsTextFile, rdd.saveToCassandra, ... las necesidades de memoria del controlador serán muy bajas. Pocos 100 de MB harán. El controlador también es responsable de entregar archivos y recopilar métricas, pero no de participar en el procesamiento de datos.
Si el trabajo requiere que el conductor participe en el cálculo , como por ejemplo, algún algoritmo ML que necesita materializar los resultados y transmitirlos en la siguiente iteración, entonces su trabajo se vuelve dependiente de la cantidad de datos que pasan por el controlador. Las operaciones como .collect
, .take
y takeSample
entregan datos al controlador y, por lo tanto, el controlador necesita suficiente memoria para asignar dichos datos.
Por ejemplo, si tiene un rdd
de 3 GB en el clúster y llama a val myresultArray = rdd.collect
, necesitará 3GB de memoria en el controlador para contener esos datos más algún espacio extra para las funciones mencionadas en el primer párrafo.