Running with Windows Subsystem for Linux#

Introduction top#

Some of the tools commonly used with SVL Simulator, like Apollo or Autoware.Auto, might require Linux operating system to run. If you don't have Linux available or prefer using Windows, it's now possible to run Linux-exclusive programs using Windows Subsystem for Linux (WSL).

Features available in WSL are dependent on its version, which is tied to the version of Windows 10. Starting with build 20149, WSL supports GPU Paravirtualization (GPU-PV) that will let you run CUDA applications inside your WSL instance and in Docker containers. Build 21362 adds support for GUI applications (as an alternative, you can also set up desktop environment).

Installation top#

NOTE: At the time of writing, most of the drivers and software required to use GPU-PV in WSL are still in preview. This might require using their pre-release versions. Details can be found in specific sub-sections.

Verify Windows 10 version top#

In the Windows command line, enter:


Reported OS Build should be 20149 or higher. If the build number is lower, and your system is up to date, required Windows version is not yet a part of public release. To use it, you will have to join Windows Insider Program on Dev Channel that will let you use early builds of Windows 10. If you're interested, please follow official instructions and update your Windows version.

Install WSL 2 top#

To install WSL 2, please refer to the official documentation. We recommend using Ubuntu 18.04 or Ubuntu 20.04 Linux distribution. This tutorial will assume Ubuntu 20.04 is installed.

If you have installed WSL previously, make sure you're using WSL version 2. To check for version, enter:

wsl -l -v

The distribution you're planning to use should report 2 under VERSION. If you're using WSL 1, update it to WSL 2.

Make sure your Linux kernel version is up to date. You can update it through an elevated Windows command line, by entering:

wsl --update

Install NVIDIA drivers top#

At the time of writing, NVIDIA drivers for CUDA on WSL are still in public preview. Version 470.14 (with CUDA 11.3) or higher is required. You can check your current driver version through Windows command line, by entering:


If your driver version is older, you can download required version from official NVIDIA web page.

To verify that your GPU is working inside WSL, you can build and run one of default CUDA examples using WSL terminal:

cd /usr/local/cuda/samples/4_Finance/BlackScholes

Your console should provide you with output similar to the one shown below. This means that your GPU is accessible inside of WSL and can be used to run CUDA programs.

[./BlackScholes] - Starting...
GPU Device 0: "Pascal" with compute capability 6.1

Initializing data...
...allocating CPU memory for options.
...allocating GPU memory for options.
...generating input data in CPU mem.
...copying input data to GPU mem.
Data init done.

Executing Black-Scholes GPU kernel (512 iterations)...
Options count             : 8000000
BlackScholesGPU() time    : 0.363584 msec
Effective memory bandwidth: 220.031695 GB/s
Gigaoptions per second    : 22.003170

BlackScholes, Throughput = 22.0032 GOptions/s, Time = 0.00036 s, Size = 8000000 options, NumDevsUsed = 1, Workgroup = 128

Reading back GPU results...
Checking the results...
...running CPU calculations.

Comparing the results...
L1 norm: 1.741792E-07
Max absolute error: 1.192093E-05

Shutting down...
...releasing GPU memory.
...releasing CPU memory.
Shutdown done.

[BlackScholes] - Test Summary

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.

Test passed

Install Docker Desktop for Windows top#

If you plan to use Docker inside your WSL 2 distro, we suggest to install Docker Desktop by following official documentation. Alternatively, you can decide to skip Docker Desktop and use Docker and NVIDIA Container Toolkit installed directly from your WSL 2. We recommend the first option - this tutorial will assume Docker Desktop for Windows is used. If you insist on using the second option, you can find instructions in official NVIDIA documentation.

If you're already using Docker Desktop for Windows, make sure version 3.1 or higher is installed.

After installing and launching Docker Desktop, navigate to Settings -> General and make sure that the option Use the WSL 2 based engine is enabled. After that, navigate to Settings -> Resources -> WSL integration and make sure that integration with your WSL 2 distro is enabled.

Whenever you're using Docker from WSL, the Docker Desktop application must be running on your Windows machine - otherwise WSL won't be able to recognize service docker.

To verify that Docker environment is running properly, enter your WSL terminal and launch a sample CUDA docker image from NVIDIA:

docker run --rm -it --gpus=all --env NVIDIA_DISABLE_REQUIRE=1 nbody -gpu -benchmark

NOTE: Parameter --env NVIDIA_DISABLE_REQUIRE=1 disables CUDA version check. This is required at the time of writing due to bug in NVIDIA drivers (CUDA version reported in WSL is lower than installed).

Your console should provide you with output similar to the one shown below. This means that your GPU is accessible inside of Docker containers and can be used to run CUDA programs.

Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance.
        -fullscreen       (run n-body simulation in fullscreen mode)
        -fp64             (use double precision floating point values for simulation)
        -hostmem          (stores simulation data in host memory)
        -benchmark        (run benchmark to measure performance)
        -numbodies=<N>    (number of bodies (>= 1) to run in simulation)
        -device=<d>       (where d=0,1,2.... for the CUDA device to use)
        -numdevices=<i>   (where i=(number of CUDA devices > 0) to use for simulation)
        -compare          (compares simulation results running once on the default GPU and once on the CPU)
        -cpu              (run n-body simulation on the CPU)
        -tipsy=<file.bin> (load a tipsy model file for simulation)

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.

> Windowed mode
> Simulation data stored in video memory
> Single precision floating point simulation
> 1 Devices used for simulation
GPU Device 0: "Pascal" with compute capability 6.1

> Compute 6.1 CUDA device: [NVIDIA GeForce GTX 1080]
20480 bodies, total time for 10 iterations: 16.788 ms
= 249.832 billion interactions per second
= 4996.645 single-precision GFLOP/s at 20 flops per interaction

Set up desktop environment (optional) top#

If you want to run any GUI-based applications inside your WSL or Docker environment, you have configure X Window System. By default, display options inside of WSL are not configured and no valid output device is registered. This means not only that GUI will not be displayed, but also that any program attempting to output something to screen might not work correctly or fail to launch.

If you have Windows 10 build 21362 or higher, you don't have to do anything - along your WSL instance, WSLg should have been automatically installed. WSLg pipes X11 and Wayland (used to run Linux GUI applications) directly into Windows graphical user interface. This means that any GUI application launched inside WSL will simply open on your Windows desktop. To verify that's the case, run any GUI-based application from your WSL instance. As an example, you can use one of OpenGL test applications. In your WSL terminal, enter:


This should open new window with three spinning gears. If your Linux distro does not have this installed by default, you can get glxgears application from mesa-utils package:

sudo apt install mesa-utils

If you are able to launch Linux GUI applications directly on your Windows desktop, you can safely skip the rest of this section. However, if your Windows build version is lower than 21362 and you don't have access to WLSg, you can still use GUI applications through remote desktop.

Remote desktop solution shown here will use xfce4 desktop environment for Linux and xrdp RDP server. Both modified configuration files (/etc/xrdp/xrdp.ini and /etc/xrdp/ are backed up with .bak extension if you ever need their original version.

To install and configure the remote desktop for WSL, run commands shown below in your WSL terminal:

sudo apt-get install xrdp
sudo apt -y install xfce4
sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak
sudo sed -i 's/3389/3390/g' /etc/xrdp/xrdp.ini
sudo sed -i 's/max_bpp=32/#max_bpp=32\nmax_bpp=128/g' /etc/xrdp/xrdp.ini
sudo sed -i 's/xserverbpp=24/#xserverbpp=24\nxserverbpp=128/g' /etc/xrdp/xrdp.ini
sudo cp /etc/xrdp/ /etc/xrdp/
sudo sed -i 's+test -x /etc/X11/Xsession \&\& exec /etc/X11/Xsession+#test -x /etc/X11/Xsession \&\& exec /etc/X11 Xsession+g' /etc/xrdp/
sudo sed -i 's+exec /bin/sh /etc/X11/Xsession+#exec /bin/sh /etc/X11/Xsession\nstartxfce4+g' /etc/xrdp/

To start RDP server that will allow you to connect to WSL desktop, run:

sudo /etc/init.d/xrdp start

After the setup, run Remote Desktop Connection application in your Windows environment (mstsc from Windows start menu). Enter localhost:3390 as the address and click Connect.

You will be welcomed with xrdp login screen. Enter your WSL credentials and click OK to connect.

You should now be seeing the xfce4 desktop of your Linux distro. You can use it to run any GUI-based applications.

Networking considerations top#

Compared to using Docker on Linux, using it on Windows through Docker Desktop application with WSL 2 backend has some significant differences in networking. Whenever you want to use any kind of networking functionality in container running on Docker Desktop, make sure to take points below into account.

  • --net=host option for docker run will not behave as expected. Docker daemon runs inside an isolated network namespace, which from the perspective of Docker container is a host network. You won't be able to access containers started with this option through usual means.
  • Docker Desktop provides special host entry (host.docker.internal) that resolves to your host machine. It always resolves to reachable IP from the container, and resolves to on the host. If you can't connect to your container through localhost, try using host.docker.internal instead.
  • Since you can't use --net=host option, all of the ports that will be used to communicate with the container have to be explicitly exposed using -p flag (see official documentation for details). They will be tunneled both to WSL 2 network namespace and Windows host.