Configuración de vLLM para máxima eficiencia

Origen

Parámetros del motor vLLM que discutiremos:

  • max-num-batched-tokens
  • max-model-len
  • gpu-memory-utilization
  • enable-prefix-caching
  • enable-chunked-prefill
  • enforce-eager

max-model-len:

TL;DR en función del número máximo de tokens utilizados (entrada + salida)

  • Por defecto, la longitud máxima del modelo es igual a la longitud máxima de contexto de su modelo. Por ejemplo, para el modelo llama 3 8B instruct, será de 8192.
  • Si puede determinar la longitud máxima de contexto para su caso de uso y si es menor que la longitud máxima de contexto de su modelo, es mejor establecer este parámetro en ese valor.
  • Esto no solo evitará errores de falta de memoria al cargar o usar el modelo, sino que también ayudará a configurar otros parámetros, como max-num-batched-tokens y gpu-memory-utilization.
  • El valor incluye el número de tokens de entrada y salida, por lo que, si en su caso el número total de tokens no supera, digamos, 2046, establezca este parámetro en ese valor.

max-num-batched-tokens:

TL;DR empiece con max-model-len, luego intente duplicar ese valor: max-model-len * 2, luego * 3… hasta que obtenga un error de falta de memoria o una advertencia de expulsión aquí. Elija el valor que proporcione un buen rendimiento. Si usa enable-chunked-prefill, empiece con un valor menor, por ejemplo 128, y pruebe diferentes valores. Consulte las explicaciones a continuación.

  • Tenga en cuenta que este parámetro indica el número de tokens, no el tamaño del paquete.
  • Cada solicitud debe pasar por una fase de prellenado (cálculo de los valores KV para los tokens de entrada y distribución de estos bloques en el caché KV), y luego una fase de decodificación, en la que se realiza un cálculo recursivo directo para obtener los tokens uno por uno.
  • Por lo tanto, el valor mínimo de este parámetro es la longitud máxima del modelo que ha establecido para el prellenado (a menos que esté usando chunked-prefill, sobre esto se hablará más adelante).
  • Cuantos más tokens haya en el paquete, más prellenados habrá, lo que significa que el primer token se generará más rápido. El planificador vLLM por defecto prefiere los prellenados.
  • Por lo tanto, un tamaño de paquete grande puede ayudar a aumentar la capacidad de procesamiento, pero no funciona en todos los casos, ya que la capacidad y la latencia también dependen de la relación entre recursos computacionales y memoria de la GPU (más detalles en la sección chunked-prefill), y, en general, los prellenados requieren más recursos computacionales, por lo que alcanzan rápidamente el máximo número de tokens en el paquete que podemos guardar.
  • Por lo tanto, es mejor comenzar con el valor max-model-len, intentar duplicarlo y ver cómo cambia el rendimiento hasta que aparezca un error de falta de memoria o una advertencia de expulsión, como se indica aquí, para elegir la cantidad adecuada de tokens en el paquete. Luego, intente aplicar esta teoría para entender cómo funciona su sistema.

enable-prefix-caching:

Resumen active esta opción a menos que esté usando enable-chunked-prefill

  • Almacena los valores KV calculados para su uso posterior, lo que permite ahorrar mucho tiempo.
  • Si la mayor parte de su solicitud permanece inalterada al ingresar datos, notará un aumento más significativo en el rendimiento en comparación con la configuración en la que una pequeña parte de los tokens de la solicitud permanece inalterada.
  • Si se utiliza el parámetro enable-chunked-prefill, este parámetro no es válido (en el momento de la publicación de este artículo).

gpu-memory-utilization:

TL;DR cuanto más, mejor, a menos que aparezca un error de falta de memoria. Por defecto 0,9

  • Cuanta más memoria de la GPU se destine a almacenar el caché KV, mejor será el rendimiento.
  • Reduzca este valor si ha experimentado errores de falta de memoria o si la GPU está realizando otra tarea que requiere reducir este valor.

enforce-eager:

TL;DR si hay falta de memoria, active esta función

  • Al usarla, no se creará un grafo CUDA, lo que puede afectar el rendimiento, pero permitirá ahorrar memoria que se habría necesitado para el grafo.
  • En algunas configuraciones, el grafo CUDA no tendrá un impacto significativo en el rendimiento, y la memoria ahorrada puede ser útil para aumentar los valores de los parámetros mencionados anteriormente, como gpu-memory-utilization, max-num-batched-tokens, etc.

enable-chunked-prefill:

TL;DR intente activar esta función y use tokens en paquetes comenzando con un valor de 128 y aumentando gradualmente. Compare con la configuración sin este parámetro. Consulte más abajo.

  • La fase de decodificación es menos exigente en recursos computacionales en comparación con el prellenado (multiplicación de un vector por una matriz en lugar de multiplicación de matrices), pero más exigente en memoria, ya que necesita leer los valores KV calculados.
  • Si desea saber más, consulte este artículo y esta página de vLLM.
  • Como ya se mencionó, por defecto, el planificador vLLM prefiere el prellenado, que requiere recursos computacionales, mientras que durante la decodificación la memoria se convierte en el punto débil, impidiendo el uso completo de la decodificación con bajos recursos computacionales y alta demanda de memoria, ya que se requiere leer los valores KV.
  • Chunk prefill divide la fase de prellenado en fragmentos, lo que permite reducir el número de tokens en el paquete y formar primero el paquete, recolectando solicitudes de decodificación y agregando solicitudes de división en fragmentos para el prellenado, para utilizar eficientemente los recursos de la GPU, combinando tanto el prellenado fragmentado como recursos computacionales intensivos, como también suficientes solicitudes de decodificación con bajos recursos computacionales pero alta demanda de memoria.
  • Vuelva a intentar activar esta función y use un número pequeño de tokens en el paquete, por ejemplo 128, y aumente gradualmente hasta obtener los rendimientos deseados de capacidad y latencia.
  • Este método puede ayudar a reducir la latencia entre tokens, ya que la decodificación tiene prioridad debido al tamaño pequeño del paquete (lo que reduce la carga en la memoria), pero puede afectar la capacidad, por lo que es necesario probar diferentes tamaños de paquetes y comparar los resultados cuando este parámetro no está activado.

Ejemplo:

  • Usaremos la API de puntos de entrada de vLLM aquí en lugar del servidor compatible con OpenAI.
  • Para iniciar el servidor sin prellenado fragmentado, puede usar el siguiente ejemplo:
python3 -m vllm.entrypoints.api_server — model MaziyarPanahi/Meta-Llama-3–8B-Instruct-GPTQ — gpu-memory-utilization 0.95 — port 5000 — dtype half — enforce-eager — max-model-len 4096 — max-num-batched-tokens 8192 — enable-prefix-caching
  • Si está activada la función de prellenado fragmentado, el comando puede verse así:
python3 -m vllm.entrypoints.api_server — model MaziyarPanahi/Meta-Llama-3–8B-Instruct-GPTQ — gpu-memory-utilization 0.95 — port 5000 — dtype half — enforce-eager — max-model-len 4096 — max-num-batched-tokens 256 — enable-chunked-prefill
  • Envíe una solicitud a la endpoint del servidor indicado anteriormente para verificar el rendimiento con diferentes parámetros.
  • Realice un benchmark usando los scripts proporcionados por vLLM, y también intentaré escribir un script similar y compartirlo aquí.

Del autor