Cómo usar la memoria de vídeo como SWAP

Actualmente es habitual encontrar tarjetas gráficas con 256 MB de memoria de vídeo o incluso más. Es difícil sacar provecho a esta cantidad de memoria de una forma que no sea jugando. Cuando no se están ejecutando aplicaciones gráficas buena parte de esta memoria está en desuso. Si piensas que es una pena desperdiciar esa cantidad de MB de una una memoria de alto rendimiento te interesará saber que es posible utilizar la memoria de vídeo no usada como si fuese un dispositivo de bloques. Esto es, podemos usar la memoria de tarjeta gráfica como un disco RAM o como memoria de intercambio (SWAP).

Hasta aquí todo muy bonito pero existen una pega:

  • Para que podamos usar parte de la memoria de vídeo es necesario que nuestro driver de vídeo permita controlar la cantidad de dicha memoria que usará el propio driver, para así asegurarnos de que resto de memoria queda libre para nosotros.
  • La mayoría de drivers de vídeo binarios (propietarios) no permiten establecer la cantidad de memoria que utilizan, lo que implica que para poder sacar provecho de esta guía es muy probable que tengamos que usar un driver libre que por norma general no disponen de aceleración.
  • Por tanto casi con total seguridad deberemos elegir entre un sistema con aceleración de vídeo pero con menos SWAP o un sistema sin aceleración pero con una SWAP mas grande y rápida. Prescindir de la aceleración de vídeo en un servidor es comprensible pero no tanto en un equipo de escritorio.

Antes de continuar leyendo consulta la documentación de tu driver de vídeo para saber si existe forma de limitar la cantidad de memoria de vídeo que usa. Normalmente esto se consigue con la opción VideoRam n dentro de la sección Section "Device" del archivo /etc/X11/xorg.conf, siendo n la cantidad de memoria que usará el driver expresada en kBytes. Como ya he dicho, la mayoría de drivers propietarios y algunos de los drivers libres ignoran esta opción de Xorg. Por ejemplo podemos usar el driver vesa (VIDEO_CARDS="vesa" en /etc/make.conf) de Xorg que sí acepta dicho parámetro. Un ejemplo de configuración de Xorg para limitar a 4MB con dicho driver:

Section "Device"
        Identifier      "vesacard"
        Driver          "vesa"
        VideoRam        4096
EndSection

Teniendo ya la certeza de que nuestro driver de vídeo no va a ocupar más memoria de la que nos interesa, es hora de saber cómo conseguirlo. La mayoría de estas instrucciones están sacadas del artículo del Wiki de Gentoo en inglés "TIP Use memory on video card as swap".

Manos a la obra

AVISO: No me hago responsable de cualquier fallo o pérdida producido por el seguimiento de estas instrucciones.

Preparación del kernel

Device Drivers  --->
 [M] Memory Technology Device (MTD) support  --->
  [M]   Direct char device access to MTD devices
  [M]   Caching block device access to MTD devices
        Self-contained MTD device drivers  --->
        [M]   Physical system RAM (NEW)

Localizar el espacio de memoria que podemos usar

Tenemos que buscar la memoria de vídeo en el espacio PCI. La forma más sencilla es usar lspci:

# emerge -n sys-apps/pciutils
# lspci -vvv
...
01:00.0 VGA compatible controller: nVidia Corporation Unknown device 0407 (rev a1) (prog-if 00 [VGA controller])
        Subsystem: Dell Unknown device 0228
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 16
        Region 0: Memory at fd000000 (32-bit, non-prefetchable) [size=16M]
        Region 1: Memory at e0000000 (64-bit, prefetchable) [size=256M]
        Region 3: Memory at fa000000 (64-bit, non-prefetchable) [size=32M]
        Region 5: I/O ports at df00 [size=128]
        [virtual] Expansion ROM at fea00000 [disabled] [size=128K]
        Capabilities: [60] Power Management version 2
                Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
                Status: D0 PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [68] Message Signalled Interrupts: Mask- 64bit+ Queue=0/0 Enable-
                Address: 0000000000000000  Data: 0000
        Capabilities: [78] Express (v1) Endpoint, MSI 00
                DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <512ns, L1 <4us
                        ExtTag+ AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
                DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x16, ASPM L0s L1, Latency L0 <512ns, L1 <4us
                        ClockPM- Suprise- LLActRep- BwNot-
                LnkCtl: ASPM L0s L1 Enabled; RCB 128 bytes Disabled- Retrain- CommClk+
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x16, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
        Kernel driver in use: nvidia
        Kernel modules: nvidia

...

La parte que nos interesa es la marcada como prefetchable. En mi caso la parte interesante está en la "Region 1" con un tamaño de 256M y lo más importante: comienza en la dirección e0000000 (un valor de 32 bits expresado en hexadecimal).

AVISO: Esto es solo un ejemplo concreto de mi tarjeta gráfica. En tu ordenador los resultados variarán en función de la tarjeta instalada.

Calculando el rango a usar

Al módulo phram tenemos que proporcionarle dos parámetro: (1)la dirección de inicio del rango de memoria que usaremos y (2)el tamaño del rango.

(1)Para calcular la dirección de inicio de nuestro rango a partir de la cual podemos empezar a usar memoria de vídeo no tenemos más que añadir a la dirección marcada por lspci la cantidad de memoria que tenía reservada el driver de vídeo. Siguiendo con los datos de los ejemplos, la dirección de inicio de la memoria de vídeo indicada por lspci es e0000000 (en hexadecimal, recordemos) y la memoria que tenía reservada el driver de vídeo era de 4MBytes. Para poder sumar ambos valores hay que pasar 4MBytes a bytes y expresarlo en hexadecimal:
En decimal: 4*1024*1024 = 4194304
En hexadecimal: 0x400000

Para hacer los cálculos y conversiones podemos usar cualquier calculadora, por ejemplo esta. Sumando ambos valores obtenemos:
0xe0000000+0x400000 = 0xE0400000

(2)Como de los 256M de memoria de vídeo disponibles en la "Region 1" 8M ya está reservados para el driver de vídeo, los restantes 252M son el tamaño de nuestro rango. Para indicar el tamaño del rango no es necesario hacer cálculos, simplemete añadiremos Mi al final.

Con estos cálculos, la forma de pasar los valores al módulo phram es:

# modprobe phram phram=VRAM,0xE0400000,252Mi

Por supuesto, para no tener que indicarlos cada vez en la línea de comandos podemos incluirlos en un fichero dentro de /etc/modules.d/ de la forma habitual en Gentoo.

Podemos comprobar el resultado ejecutando

# cat /proc/mtd
dev: size erasesize name
mtd0: 10000000 00001000 "VRAM"

Crear los dispositivos

Como en Gentoo usamos UDEV no es necesario crear los dispositivos a mano ya que al cargar los módulos se crean automáticamente:

# modprobe mtdchar
# ls -1 /dev/mtd*
/dev/mtd0
/dev/mtd0ro
# modprobe mtdblock
# ls -1 /dev/mtd*
/dev/mtd0
/dev/mtd0ro
/dev/mtdblock0

Usando la memoria

Como he dicho, podemos usar la memoria de vídeo como un disco RAM o como memoria de intercambio (SWAP). En ambos casos hay que crear un sistema de ficheros en la nueva memoria. Para el caso de la SWAP:

# mkswap /dev/mtdblock0
# swapon /dev/mtdblock0

Esto creará la estructura de la SWAP en la memoria de vídeo de la tarjeta y la activará como memoria SWAP del sistema para empezar a ser usada al instante. En caso de tener más de una memoria SWAP puedes indicar la prioridad de uso de cada una, bien mediante el parámetro -p en línea de comandos (swapon), bien con la opción pri= en /etc/fstab. Consulta la página 2 del manual de swapon.

Agradecido

Don Stolz, me he creado una cuenta en su Blog, nada mas para poder decir: WOW!! Gracias!!

Salud!

MTD_PHRAM

Don Stolz, le faltó añadir a la configuración del kernel:

Memory Technology Device (MTD) support
   Self-contained MTD device drivers  --->
      M Physical system RAM   <---- como módulo

Salud!

¡Corregido!

Muchas gracias.

Saludozzzzzzzz