Un error de dimensionamiento en el kernel de Linux puede impedir que un sistema mapee múltiples BAR (Registros de Dirección Base) reescalables de 32 GB cuando están conectados detrás de un interruptor PCIe, bloqueando efectivamente la comunicación peer-to-peer (P2P) de alto rendimiento entre GPUs. Esto ocurre porque el kernel subestima la cantidad de espacio de direcciones requerido para acomodar los huecos de alineación entre los grandes bloques de memoria y las pequeñas ventanas de registros.

El problema del hueco de alineación

Cuando una GPU utiliza BAR reescalable, mapea toda su VRAM —por ejemplo, 32 GB— en el espacio de direcciones de la CPU. Sin embargo, muchas GPUs también requieren un pequeño BAR de 'doorbell' para la comunicación con el controlador. Debido a que estos BAR grandes deben comenzar en límites específicos (por ejemplo, 32 GB), un doorbell de 2 MB colocado inmediatamente después de un BAR de 32 GB todavía obliga a que el siguiente dispositivo comience en el siguiente incremento de 32 GB.

El kernel Linux 7.0 contiene una regresión en la función `pbus_size_mem()`. Calcula la ventana total del interruptor sumando los tamaños de sus hijos. Debido a que trata estos valores como una suma simple en lugar de contabilizar los huecos de alineación, cree que las tarjetas cabrán en un espacio más pequeño del que realmente ocupan, lo que provoca errores de 'can't assign; no space' (no se puede asignar; sin espacio).

Un dibujo de un estacionamiento con un letrero que dice 'ventana del interruptor' y cuatro bahías, mostrando dos limusinas R9700 estacionadas dentro mientras otras esperan afuera.
Una ilustración conceptual del error 'can't assign; no space' causado por la falla del kernel al no contabilizar los huecos de alineación.doug.sh

Esta ilustración proporciona una metáfora visual para el error de dimensionamiento donde el kernel cree que el espacio disponible es suficiente a pesar de los requisitos de alineación reales.

“El kernel le dio al interruptor una ventana de unos 128.6 GB. Con el doorbell colocado después de cada BAR, la forma en que Linux 7.0 los organiza, las cuatro ventanas abarcan 224 GB (tres ranuras de 64 GB más los 32 GB de la última tarjeta y su doorbell).”

— Fitting Four 32 GB Resizable BARs Behind a PCIe Switch on Linux
Un diagrama técnico que muestra tres formas diferentes de mapear las ventanas de memoria de la GPU en un interruptor PCIe, ilustrando el error de cálculo del kernel frente a la solución de relleno del módulo.
Comparación de cómo el kernel Linux 7.0 calcula las ventanas del interruptor frente al método de relleno manual utilizado por el módulo gpu-rebar-layout.doug.sh

Este diagrama ilustra el problema específico del hueco de alineación donde el cálculo de 'suma simple' del kernel no tiene en cuenta el relleno de 32 GB requerido por los BAR grandes.

Omitiendo el error de dimensionamiento del kernel

Para resolver esto, un módulo de kernel personalizado (`gpu-rebar-layout`) opera dentro del initramfs, el pequeño sistema de archivos desde el cual el kernel arranca antes de que se carguen cualquier controlador de GPU. El módulo identifica las GPUs de destino, establece el tamaño de su BAR0 al máximo soportado (por ejemplo, 32 GB) y luego elimina y vuelve a escanear los puertos raíz por encima del interruptor PCIe.

Durante este reescaneo, el módulo aumenta manualmente la alineación de cada BAR de memoria más pequeño para que coincida con el BAR más grande en ese segmento. Esto asegura que cada ventana R9700 ocupe exactamente 64 GB de espacio de direcciones, permitiendo que el asignador del kernel coloque con éxito todos los dispositivos sin que se solapen o se agote el espacio.

Ganancias de rendimiento y compensaciones

Mapear correctamente estos BAR es fundamental para la comunicación peer-to-peer (P2P), que permite a las GPUs copiar datos entre sí sin involucrar a la CPU. En pruebas con cuatro AMD Radeon AI PRO R9700, esta configuración logró 14.0 GB/s por par, con cuatro tarjetas copiando en anillo a una velocidad combinada de 54.7 GB/s.

La solución alternativa implica compensaciones específicas: debe cargarse muy temprano en el proceso de arranque y puede requerir desactivar las funciones de audio de la GPU para liberar más espacio de direcciones. Además, aunque actualmente se está desarrollando una serie de 14 parches para el kernel de Linux para abordar correctamente este error de dimensionamiento, el módulo sigue siendo un parche necesario para las versiones actuales.

Qué dicen los lectores de Hacker News

  • Alternativa: Los comentaristas señalaron que el autor de la publicación explicó que desarrolló el módulo para permitir transferencias peer-to-peer entre cuatro GPUs, señalando que desactivar esta función reducía significativamente el rendimiento durante las tareas de prellenado. comentario ↗
  • Nota técnica: Un comentarista aclaró que el problema surge de las limitaciones de firmware en ciertas placas base, donde la BIOS restringe el espacio de direcciones disponible para dispositivos PCI, causando que los BAR grandes se solapen y excedan las ranuras disponibles. comentario ↗
  • Escéptico: Varios comentaristas expresaron su frustración por el hecho de que las capas de software y las configuraciones ocultas impiden que el hardware utilice todas sus capacidades físicas, cuestionando por qué un espacio de direcciones virtuales tan grande no se gestiona de manera más sencilla. comentario ↗

Resumen de opiniones del hilo de Hacker News; no son hechos verificados. Leer el debate completo ↗