Sobre el surgimiento del soporte de CUDA en WSL 2

Microsoft, respondiendo a numerosas solicitudes de los usuarios, presentó en la conferencia Build en mayo de 2020 una nueva característica del Subsistema de Windows para Linux 2 (WSL 2): soporte para aceleradores de video. Esto le permitirá ejecutar aplicaciones informáticas ad-hoc en WSL 2. El soporte de GPU allanará el camino para herramientas profesionales y ayudará a resolver tareas en WSL 2 que actualmente solo son posibles en Linux. Ahora, se pueden resolver tareas similares en Windows, utilizando las capacidades de la GPU.



Aquí es extremadamente importante que el soporte para la arquitectura de hardware y software de la computación paralela NVIDIA CUDA llegue a WSL .



El material que estamos publicando ha sido traducido por expertos de NVIDIA. Aquí hablaremos sobre lo que puede esperar de CUDA en la versión de Vista previa pública de WSL 2.





Ejecutar marcos de Linux AI en contenedores WSL 2



¿Qué es el WSL?



WSL es una característica de Windows 10 que le permite usar las herramientas de línea de comandos de Linux directamente en Windows sin tener que lidiar con las complejidades de aplicar una configuración de arranque dual. WSL es un entorno en contenedores que está estrechamente integrado con Microsoft Windows. Esto le permite ejecutar aplicaciones de Linux con aplicaciones tradicionales de Windows y con aplicaciones modernas distribuidas a través de Microsoft Store.



WSL es principalmente una herramienta para desarrolladores. Si está trabajando en algunos proyectos en contenedores de Linux, significa que puede hacer las mismas cosas localmente, en una computadora con Windows, utilizando herramientas conocidas de Linux. Por lo general, para ejecutar dichas aplicaciones en Windows, necesita pasar mucho tiempo configurando el sistema, necesita algunos marcos de terceros, bibliotecas. Ahora, con el lanzamiento de WSL 2, todo ha cambiado. Gracias a WSL 2, el soporte completo para el kernel de Linux llegó al mundo de Windows.



La tecnología de paravirtualización WSL 2 y GPU (GPU Paravirtualization, GPU-PV) permitió a Microsoft llevar el soporte de Linux para Windows a un nuevo nivel, lo que permitió lanzar cargas informáticas diseñadas para la GPU. A continuación, veremos más de cerca cómo se ve la GPU en WSL 2.



Si está interesado en el tema de soporte para aceleradores de video en WSL 2, eche un vistazo a este material y este repositorio.



CUDA en WSL



Para aprovechar las características de la GPU en WSL 2, debe tener un controlador de video que sea compatible con Microsoft WDDM en su computadora . Dichos controladores son creados por fabricantes de tarjetas de video, como NVIDIA.



La tecnología CUDA permite desarrollar programas para aceleradores de video NVIDIA. Esta tecnología ha sido compatible con WDDM en Windows durante muchos años. El nuevo contenedor WSL 2 de Microsoft proporciona capacidades informáticas aceleradas por GPU que la tecnología CUDA puede aprovechar, lo que permite que los programas basados ​​en CUDA se ejecuten en el entorno WSL. Para obtener más detalles, consulte la Guía del usuario de CUDA en WSL.



El soporte CUDA en WSL está incluido en los controladores NVIDIA para WDDM 2.9. Estos controladores son fáciles de instalar en Windows. Los controladores de modo de usuario WSL CUDA (libcuda.so) están disponibles automáticamente dentro del contenedor y el cargador puede detectarlos.



El equipo de desarrollo de controladores NVIDIA ha agregado soporte para WDDM y GPU-PV al controlador CUDA. Esto se hace para que estos controladores puedan funcionar en un entorno Linux que se ejecuta en Windows. Estos controladores todavía están en estado de Vista previa, su lanzamiento tendrá lugar solo cuando tenga lugar el lanzamiento oficial de WSL con soporte de GPU. Los detalles sobre la versión del controlador se pueden encontrar aquí .



La siguiente figura muestra un diagrama de cómo conectar el controlador CUDA a WDDM dentro de un huésped Linux.





Controlador WDDM con modo de usuario habilitado para CUDA que se ejecuta en un invitado Linux



Suponga que es un desarrollador que instaló la distribución WSL en la última compilación de Windows de Fast Ring (compilación 20149 o anterior) Microsoft Windows Insider Program (WIP). Si cambió a WSL 2 y tiene una GPU NVIDIA, puede probar el controlador y ejecutar su código de cómputo GPU en WSL 2. Para hacer esto, simplemente instale el controlador en el sistema host de Windows y abra el contenedor WSL. Aquí podrá trabajar con aplicaciones que utilizan CUDA sin ningún esfuerzo adicional. La siguiente figura muestra cómo se ejecuta una aplicación TensorFlow con capacidades CUDA en un contenedor WSL 2.





El contenedor TensorFlow se ejecuta en WSL 2



El hecho de que CUDA ahora esté disponible en WSL permite que las aplicaciones se ejecuten en WSL que anteriormente solo se podían ejecutar en un entorno Linux normal.



NVIDIA todavía está trabajando activamente en este proyecto y haciéndole mejoras. Entre otras cosas, estamos trabajando para agregar API a WDDM que previamente fueron diseñadas exclusivamente para Linux. Esto conducirá al hecho de que en WSL, sin esfuerzos adicionales por parte del usuario, más y más aplicaciones podrán funcionar.



Otro tema de interés para nosotros es el rendimiento. Como se mencionó, el soporte de GPU en WSL 2 toma en serio la tecnología GPU-PV. Esto puede afectar negativamente la velocidad de realizar pequeñas tareas en la GPU, en situaciones en las que no se utilizará la canalización. En este momento estamos trabajando para lograr la mayor reducción posible de tales efectos.



NVML



El paquete de controladores original no incluye la tecnología NVML, nos esforzamos por solucionar esto planeando agregar soporte NVML y soporte para otras bibliotecas a WSL.



Comenzamos con el controlador CUDA principal, que permitirá a los usuarios ejecutar la mayoría de las aplicaciones CUDA existentes, incluso en una etapa temprana de la introducción del soporte CUDA en WSL. Pero resultó que algunos contenedores y aplicaciones usan NVML para obtener información de GPU incluso antes de cargar CUDA. Es por eso que agregar soporte NVML a WSL es una de nuestras principales prioridades. Es muy posible que pronto podamos compartir algunas buenas noticias sobre la solución de este problema.



Contenedores de GPU en WSL



Además de admitir WSL 2 DirectX y CUDA, NVIDIA está trabajando para agregar soporte para NVIDIA Container Toolkit a WSL 2 (anteriormente llamado nvidia-docker2). Las aplicaciones de GPU en contenedores que los científicos de datos crean para ejecutar en un entorno Linux local o en la nube ahora pueden, sin hacer ningún cambio, ejecutarse en WSL 2 en computadoras que ejecutan Windows.



No se requieren paquetes especiales de WSL para esto. La biblioteca de tiempo de ejecución de NVIDIA (libnvidia-container) puede detectar dinámicamente libdxcore y usarlo cuando el código se ejecuta en un entorno WSL 2 acelerado por GPU. Esto sucede automáticamente después de instalar los paquetes Docker y NVIDIA Container Toolkit, al igual que en Linux. Esto le permite, sin esfuerzo adicional, ejecutar contenedores en WSL 2 que utilizan la potencia de la GPU.



Recomendamos encarecidamente que aquellos que quieran usar la opción --gpusinstalen las últimas herramientas de Docker (19/03 o posterior). Para habilitar el soporte de WSL 2, siga las instrucciones para su distribución de Linux e instale la última versión disponible nvidia-container-toolkit.



¿Cómo funciona? Todas las tareas específicas de WSL 2 se resuelven utilizando la biblioteca libnvidia-container . Ahora esta biblioteca puede, en tiempo de ejecución, detectar la presencia de libdxcore.so y usar esta biblioteca para detectar todas las GPU visibles para esta interfaz.



Si estas GPU necesitan usarse en un contenedor, entonces, usando libdxcore.so, se accede a la ubicación de los controladores, a la carpeta que contiene todas las bibliotecas de controladores para el sistema host de Windows y WSL 2. La biblioteca libnvidia-container.so es responsable de configurar el contenedor de tal manera que sea posible acceder correctamente a la tienda de controladores. Esta misma biblioteca es responsable de configurar las bibliotecas base compatibles con WSL 2. Esto se muestra esquemáticamente en la siguiente figura.





El descubrimiento de la tienda de controladores y el esquema de asignación de contenedores utilizado por libnvidia-container.so en WSL 2



También es diferente de la lógica utilizada fuera de WSL. Este proceso se abstrae completamente con libnvidia-container.so y debería ser lo más transparente posible para el usuario final. Una de las limitaciones de esta versión inicial es que no puede seleccionar GPU en entornos que tienen múltiples GPU. Todas las GPU siempre están visibles en el contenedor.



Cualquier contenedor NVIDIA Linux con el que ya esté familiarizado puede ejecutarse en un contenedor WSL. NVIDIA admite las herramientas y flujos de trabajo de Linux más interesantes utilizados por los profesionales. Descargue el contenedor que le interesa de NVIDIA NGC y pruébelo.



Ahora le mostraremos cómo ejecutar contenedores TensorFlow y N-body en WSL 2, que están diseñados para usar GPU NVIDIA para acelerar los cálculos.



Ejecutando el contenedor N-body 



Instale Docker usando el script de instalación:



user@PCName:/mnt/c$ curl https://get.docker.com | sh


Instale el kit de herramientas de contenedor NVIDIA. La compatibilidad con WSL 2 está disponible a partir de nvidia-docker2 v2.3 y la biblioteca de tiempo de ejecución libnvidia-container 1.2.0-rc.1.



Vamos a configurar los repositorios stabley experimentaly la clave GPG. Los cambios en el código de tiempo de ejecución que están diseñados para admitir WSL 2 están disponibles en el repositorio experimental.



user@PCName:/mnt/c$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)

user@PCName:/mnt/c$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -

user@PCName:/mnt/c$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

user@PCName:/mnt/c$ curl -s -L https://nvidia.github.io/libnvidia-container/experimental/$distribution/libnvidia-container-experimental.list | sudo tee /etc/apt/sources.list.d/libnvidia-container-experimental.list


Instale los paquetes de tiempo de ejecución de NVIDIA y sus dependencias:



user@PCName:/mnt/c$ sudo apt-get update
user@PCName:/mnt/c$ sudo apt-get install -y nvidia-docker2


Abramos un contenedor WSL e iniciemos el demonio Docker en él. Si todo se hace correctamente, después de eso puede ver los mensajes de servicio dockerd.



user@PCName:/mnt/c$ sudo dockerd




Inicio del demonio Docker



En otra ventana WSL, cargue e inicie el contenedor de simulación de N cuerpos. Es necesario que el usuario que realiza esta tarea tenga suficiente autoridad para cargar el contenedor. Los siguientes comandos pueden necesitar ejecutarse usando sudo. En la salida puede ver información sobre la GPU.



user@PCName:/mnt/c$ docker run --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark




Ejecutando el contenedor N-body



Lanzar TensorFlow Container



Probemos en Docker, en el entorno WSL 2, otro contenedor popular: TensorFlow.



Descargue la imagen de TensorFlow Docker. Para evitar problemas al conectarse a Docker, ejecute el siguiente comando en modo sudo:



user@PCName:/mnt/c$ docker pull tensorflow/tensorflow:latest-gpu-py3


Guardemos la versión ligeramente modificada del tutorial de GPU del Tutorial 15 de TensorFlow en el disco del Csistema host. Este disco está, de forma predeterminada, montado en un contenedor WSL 2 como /mnt/c.



user@PCName:/mnt/c$ vi ./matmul.py
import sys
import numpy as np
import tensorflow as tf
from datetime import datetime

device_name = sys.argv[1]  # Choose device from cmd line. Options: gpu or cpu
shape = (int(sys.argv[2]), int(sys.argv[2]))
if device_name == "gpu":
    device_name = "/gpu:0"
else:
    device_name = "/cpu:0"

tf.compat.v1.disable_eager_execution()
with tf.device(device_name):
    random_matrix = tf.random.uniform(shape=shape, minval=0, maxval=1)
    dot_operation = tf.matmul(random_matrix, tf.transpose(random_matrix))
    sum_operation = tf.reduce_sum(dot_operation)

startTime = datetime.now()
with tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(log_device_placement=True)) as session:
        result = session.run(sum_operation)
        print(result)

#  
print("Shape:", shape, "Device:", device_name)
print("Time taken:", datetime.now() - startTime)


A continuación se muestran los resultados de la ejecución de este script, ejecutado desde un disco montado en un contenedor C. El script se ejecutó, primero, usando la GPU, y luego usando la CPU. Por conveniencia, la salida aquí se ha reducido.



user@PCName:/mnt/c$ docker run --runtime=nvidia --rm -ti -v "${PWD}:/mnt/c" tensorflow/tensorflow:latest-gpu-jupyter python /mnt/c/matmul.py gpu 20000




Resultados de la ejecución del script Matmul.py



Cuando se usa la GPU en el contenedor WSL 2, la ejecución del código se acelera significativamente en comparación con su ejecución en la CPU.



Realicemos otro experimento diseñado para estudiar el rendimiento de la computación GPU. Este es el código del manual de Jupyter Notebook. Después de iniciar el contenedor, debería ver un enlace al servidor Jupyter Notebook.



user@PCName:/mnt/c$ docker run -it --gpus all -p 8888:8888 tensorflow/tensorflow:latest-gpu-py3-jupyter




Ejecución de Jupyter Notebook



Ahora debería poder ejecutar las demostraciones en el entorno de Jupyter Notebook. Tenga en cuenta que para conectarse al Jupyter Notebook usando el navegador Microsoft Edge, debe usar, en lugar de 127.0.0.1localhost.



Vetensorflow-tutorialse inicia el bloc de notasclassification.ipynb.



Para ver los resultados de la aceleración de la GPU, vaya al menúCell, seleccioneRun Ally vea el registro en el contenedor WSL 2 Jupyter Notebook.





Jupyter Notebook Magazine



Esta demostración, y algunas otras en este contenedor, le permiten ver los problemas con la capa de virtualización, relacionados con una carga adicional irrazonablemente alta en el sistema al resolver tareas pequeñas. Ya hemos hablado sobre esto arriba. Como ejecutamos modelos tutoriales muy pequeños aquí, el tiempo de ejecución en la GPU es menor que el tiempo requerido para resolver problemas de sincronización. Al resolver tales tareas de "juguete" en WSL 2, la CPU puede ser más eficiente que la GPU. Estamos abordando este problema en un esfuerzo por limitar sus manifestaciones a solo cargas de trabajo muy pequeñas que no aplican la canalización.



Resumen de WSL



Para comprender cómo se agregó el soporte de GPU a WSL 2, ahora hablaremos sobre qué es el lanzamiento de Linux en Windows y cómo los contenedores ven el hardware.



Microsoft introdujo la tecnología WSL en Build en 2016. Esta tecnología rápidamente encontró un uso generalizado y se hizo popular entre los desarrolladores de Linux que necesitaban ejecutar aplicaciones de Windows como Office, junto con herramientas de desarrollo de Linux y programas relacionados.



WSL 1 le permitió ejecutar ejecutables de Linux no modificados. Sin embargo, utilizó una capa de emulación de kernel de Linux que se implementó como un subsistema de kernel NT. Este subsistema maneja llamadas de aplicaciones Linux, redirigiéndolas a los mecanismos apropiados de Windows 10.



WSL 1 era una herramienta útil, pero no era compatible con todas las aplicaciones de Linux porque necesitaba emular absolutamente todas las llamadas al sistema Linux. Además, las operaciones del sistema de archivos fueron lentas, lo que condujo a un rendimiento inaceptablemente bajo de algunas aplicaciones.



Con esto en mente, Microsoft decidió ir a otro lado y lanzó WSL 2, una nueva versión de WSL. Los contenedores WSL 2 ejecutan distribuciones completas de Linux en un entorno virtualizado, pero aún así aprovechan al máximo el nuevo sistema de contenedorización de Windows 10.



Si bien WSL 2 utiliza los servicios Hyper-V de Windows 10, no es una máquina virtual tradicional, sino un motor auxiliar de virtualización liviano. Este mecanismo es responsable de administrar la memoria virtual asociada con la memoria física, permitiendo que los contenedores WSL 2 asignen memoria dinámicamente al acceder al sistema host de Windows.



Entre los objetivos principales de la creación de WSL 2 están aumentar el rendimiento del trabajo con el sistema de archivos y garantizar la compatibilidad con todas las llamadas del sistema. Además, WSL 2 fue diseñado para mejorar el nivel de integración entre WSL y Windows. Esto le permite trabajar convenientemente con el sistema Linux que se ejecuta en el contenedor, utilizando las herramientas de línea de comandos de Windows. Esto, además, aumenta la usabilidad del sistema de archivos host, que se monta automáticamente en los directorios seleccionados del sistema de archivos contenedor.



WSL 2 se introdujo en el Programa Windows Insider como una función de Vista previa y se lanzó en la actualización más reciente de Windows 10, versión 2004.



En WSL 2, desde la última versión de Windows, hay aún más mejoras que afectan muchas cosas, desde las pilas de red hasta los mecanismos básicos de VHD del sistema de almacenamiento. Una descripción de todas las nuevas características en WSL 2 está más allá del alcance de este material. Puede obtener más información sobre ellos en esta página, que compara WSL 2 y WSL 1.



Linux core WSL 2



El kernel de Linux utilizado en WSL 2 es compilado por Microsoft a partir de la rama estable más reciente, utilizando el código fuente disponible en kernel.org. Este núcleo se ha ajustado especialmente para WSL 2, optimizado en términos de tamaño y rendimiento para garantizar que Linux se ejecute en Windows. El núcleo es compatible a través del mecanismo de actualización de Windows. Esto significa que el usuario no tiene que preocuparse por descargar las últimas actualizaciones de seguridad y mejoras del kernel. Todo esto se hace automáticamente.



Microsoft admite varias distribuciones de Linux en WSL. La compañía, siguiendo las reglas de la comunidad de código abierto, publicó en el repositorio WSL2-Linux-Kernel GitHub el código fuente del núcleo WSL 2 con las modificaciones necesarias para integrarse con Windows 10. 



Soporte de GPU en WSL



Microsoft ha agregado soporte para GPU reales que utilizan la tecnología GPU-PV a los contenedores WSL 2. Aquí, el núcleo de gráficos del sistema operativo (dxgkrnl) ordena las llamadas de los componentes en modo de usuario que se ejecutan en la máquina virtual invitada al controlador en modo kernel en el host.



Microsoft ha desarrollado esta tecnología como una capacidad WDDM, y desde su inicio ha habido varias versiones de Windows. Este trabajo se llevó a cabo con la participación de proveedores de hardware independientes (Independent Hardware Vendor, IHV). Los controladores de gráficos NVIDIA han admitido GPU-PV desde los primeros días de esta tecnología en las versiones de vista previa de los productos disponibles en el Programa Windows Insider. Se puede acceder a todas las GPU NVIDIA actualmente compatibles mediante un sistema operativo Windows que se ejecuta en modo invitado en una máquina virtual que ejecuta Hyper-V.



Para aprovechar las capacidades de GPU-PV en WSL 2, Microsoft tuvo que crear la base de su marco gráfico para el huésped Linux: WDDM con soporte para el protocolo GPU-PV. El nuevo controlador de Microsoft está detrás de dxgkrnl, el sistema responsable de soportar WDDM en Linux. El código del controlador se puede encontrar en el repositorio WSL2-Linux-Kernel.



Se espera que Dxgkrnl proporcione soporte de aceleración de GPU en contenedores WSL 2 en WDDM 2.9. Microsoft dice que dxgkrnl es un controlador de GPU de Linux basado en el protocolo GPU-PV y que no tiene nada que ver con un controlador de Windows que tenga un nombre similar.



Actualmente puede descargar la versión de vista previa del controlador NVIDIA WDDM 2.9. En los próximos meses, este controlador se distribuirá a través de Windows Update en la versión WIP de Windows, haciendo innecesaria la descarga e instalación manual del controlador.



Entendiendo GPU-PV



El controlador dxgkrnl pone a disposición, en modo de usuario del sistema invitado de Linux, el nuevo dispositivo / dev / dxg. La capa de servicio del núcleo D3DKMT, que estaba disponible en Windows, también fue portada, como parte de la biblioteca dxcore, a Linux. Interactúa con dxgkrnl usando un conjunto de llamadas privadas IOCTL.



La versión invitada de Linux de dxgkrnl se conecta al núcleo dxg en el host de Windows utilizando múltiples canales de bus VM. El núcleo dxg en el host maneja lo que proviene del proceso de Linux de la misma manera que lo que proviene de las aplicaciones normales de Windows que usan WDDM. Es decir, el kernel dxg envía lo que recibe al KMD (Kernel Mode Driver, un controlador en modo kernel único para cada VIH). El controlador en modo kernel prepara lo que recibe para enviarlo a un acelerador de gráficos de hardware. La siguiente figura muestra un diagrama simplificado de la interacción entre el dispositivo Linux / dev / dxg y KMD.





Un diagrama simplificado de cómo los componentes de host de Windows permiten que el dispositivo dxg funcione en un huésped Linux



Cuando se trata de proporcionar este tipo de comportamiento en los invitados de Windows, los controladores NVIDIA han sido compatibles con GPU-PV en Windows 10 durante bastante tiempo. Las GPU NVIDIA se pueden usar para acelerar la salida de cómputo y gráficos en todas las aplicaciones de Windows 10 que usan la capa de virtualización de Microsoft. Usar GPU-PV le permite trabajar con vGPU. Aquí hay algunos ejemplos de aplicaciones similares:





Así es como parece ejecutar una aplicación DirectX en un contenedor de Windows Sandbox utilizando el acelerador de video NVIDIA GeForce GTX 1070.





Aceleración de gráficos en el contenedor de Windows Sandbox por NVIDIA GeForce GTX 1070



Soporte de modo de usuario



Para agregar soporte para la representación de gráficos a WSL, el equipo de desarrollo correspondiente de Microsoft también transfirió el componente de modo de usuario dxcore a Linux.



La biblioteca dxcore proporciona una API que le permite recuperar información sobre tarjetas gráficas compatibles con WDDM disponibles en el sistema. Esta biblioteca fue concebida como un reemplazo multiplataforma de bajo nivel para la herramienta para trabajar con adaptadores DXGI en Windows y Linux. La biblioteca también abstrae el acceso a los servicios dxgkrnl (llamadas IOCTL en Linux y llamadas GDI en Windows) usando la capa API D3DKMT, que es utilizada por CUDA y otros componentes en modo de usuario que dependen del soporte WSL WDDM.



Según Microsoft, la biblioteca dxcore (libdxcore.so) estará disponible tanto en Windows como en Linux. NVIDIA planea agregar soporte para DirectX 12 y la API CUDA al controlador. Estos complementos se dirigen a las nuevas capacidades WSL disponibles con WDDM 2.9. Ambas bibliotecas API se conectarán a dxcore para que puedan indicar a dxg que reúna sus solicitudes a KMD en el sistema host.



Pruebe las nuevas funciones de WSL 2



¿Desea usar su computadora con Windows para resolver problemas reales de los campos del aprendizaje automático y la inteligencia artificial, y al mismo tiempo usar todas las comodidades de un entorno Linux? Si es así, el soporte CUDA de WSL le brinda una gran oportunidad para hacer precisamente eso. El entorno WSL es donde los contenedores CUDA Docker han demostrado ser el entorno informático más popular entre los científicos de datos.





Aquí puede obtener más información sobre el uso de la tecnología CUDA en el WSL. Aquí , en el foro dedicado a CUDA y WSL, puede compartir con nosotros sus impresiones, observaciones e ideas sobre estas tecnologías.



¿Ya probaste CUDA en WSL 2?






All Articles