Table of Contents

I have recently bought the Jetson Nano Developer Kit which is a tiny ‘AI’ computer made mainly for machine learning applications (Deep Learning inference). It comes with a 128-core Maxwell GPU, Quad-core ARM A57 @ 1.43 GHz and 4 GB 64-bit LPDDR4 Memory.

The developer kit box contains only the carrier board. Therefore we need to provide a power supply ([email protected], iPad charger works fine) and a microSD UHS-1 or higher (I used a 64GB UHS-1).

Introduction

The first step consists on preparing the microSD card with the Linux image provided by NVIDIA. Download the image from here and follow steps depending on your host OS. The image provided by NVIDIA comes with all necessary drivers for the device and CUDA/cuDNN installed. After this, connect a screen via HDMI, a keyboard/mouse, an RJ45 ethernet connection and finally connect the board to power. You’ll be asked to accept software conditions and create a username. After logging in you will see this Ubuntu screen. That’s it!

Jetson Screen

Power mode and device status

Type of power

The kit comes with two power mode 5W and 10W. When using a micro usb power and you have a keyboard/screen connected to the board, it is advised to switch to 5W mode or use a [email protected] power because the total load may exceed 2A due to peripherals attached to the kit (take a look at the User Guide for more details).

# Check Power mode
sudo nvpmodel -q
> NV Power Mode: MAXN

# Switch to 5W
sudo nvpmodel -m1
# Switch back to 10W
sudo nvpmodel -m0

Device status

You can use the following command to get some details about the device

tegrastats
> RAM 458/3965MB (lfb 467x4MB) SWAP 0/4096MB (cached 0MB)
CPU [1%@102,0%@102,0%@102,0%@102] EMC_FREQ 0% GR3D_FREQ 0% [email protected] [email protected] [email protected]
[email protected] [email protected] [email protected] POM_5V_IN 1031/1031 POM_5V_GPU 0/0 POM_5V_CPU 118/118

CUDA/NVCC compiler

Let us setup path for cuda in the bash-shell. Open bashcr in your favorite text editor and add the following paths.

#Open the file
vim ~/.bashrc

#then paste the following
export PATH=${PATH}:/usr/local/cuda/bin
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/cuda/lib64

and then reload the .bashrc

source ~/.bashrc

To check if it’s working, output the version of nvcc as follows:

nvcc --version
> nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sun_Sep_30_21:09:22_CDT_2018
Cuda compilation tools, release 10.0, V10.0.166

Congratulations!

Let us check some samples that come with CUDA. Go to the following folder and you’ll be able to find many examples that use the power of GPU.

cd /usr/local/cuda/samples/
ls
> 0_Simple  1_Utilities  2_Graphics  3_Imaging  4_Finance  5_Simulations  6_Advanced  7_CUDALibraries  EULA.txt  Makefile  bin  common

A nice tool provided is deviceQuery that allows you to see details of the GPU device you have on the Jetson Nano

cd /usr/local/cuda/samples/1_Utilities/deviceQuery
# Complie the source code
sudo make
# run it
sudo ./deviceQuery

You’ll see something like this

./deviceQuery Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

Detected 1 CUDA Capable device(s)

Device 0: "NVIDIA Tegra X1"
  CUDA Driver Version / Runtime Version          10.0 / 10.0
  CUDA Capability Major/Minor version number:    5.3
  Total amount of global memory:                 3965 MBytes (4157145088 bytes)
  ( 1) Multiprocessors, (128) CUDA Cores/MP:     128 CUDA Cores
  GPU Max Clock rate:                            922 MHz (0.92 GHz)
  Memory Clock rate:                             13 Mhz
  Memory Bus Width:                              64-bit
  L2 Cache Size:                                 262144 bytes
  Maximum Texture Dimension Size (x,y,z)         1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096)
  Maximum Layered 1D Texture Size, (num) layers  1D=(16384), 2048 layers
  Maximum Layered 2D Texture Size, (num) layers  2D=(16384, 16384), 2048 layers
  Total amount of constant memory:               65536 bytes
  Total amount of shared memory per block:       49152 bytes
  Total number of registers available per block: 32768
  Warp size:                                     32
  Maximum number of threads per multiprocessor:  2048
  Maximum number of threads per block:           1024
  Max dimension size of a thread block (x,y,z): (1024, 1024, 64)
  Max dimension size of a grid size    (x,y,z): (2147483647, 65535, 65535)
  Maximum memory pitch:                          2147483647 bytes
  Texture alignment:                             512 bytes
  Concurrent copy and kernel execution:          Yes with 1 copy engine(s)
  Run time limit on kernels:                     Yes
  Integrated GPU sharing Host Memory:            Yes
  Support host page-locked memory mapping:       Yes
  Alignment requirement for Surfaces:            Yes
  Device has ECC support:                        Disabled
  Device supports Unified Addressing (UVA):      Yes
  Device supports Compute Preemption:            No
  Supports Cooperative Kernel Launch:            No
  Supports MultiDevice Co-op Kernel Launch:      No
  Device PCI Domain ID / Bus ID / location ID:   0 / 0 / 0
  Compute Mode:
     < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 10.0, CUDA Runtime Version = 10.0, NumDevs = 1
Result = PASS

SSH and GUI configuration

GUI

Having access to Ubuntu GUI is good but it is memory consuming (around 1.4GB in my case). In the era of IoT, having access to a terminal mode (around 300MB memory) via SSH is more efficient and minimalist.

The following commands are all you need to activate/desactivate the GUI mode. Under the hypothesis that you are initially in a GUI environment

# disable GUI on boot
# After applying this command, the next time you reboot it will be on terminal mode
sudo systemctl set-default multi-user.target

# To enable GUI again
sudo systemctl set-default graphical.target

# To start GUI session on a system in terminal mode
sudo systemctl start gdm3.service

SSH

To connect to Jetson Nano via SSH, there is mainly two situations:

  • Local Network:

If your laptop, where you want to ssh from, is connected to the same network as the Jetson Nano then simply recover the local ip, noted jetson_local_ip, by ifconfig (run on the kit). Then from your host, run the following

ssh [email protected]_local_ip
# then you'll be asked to enter the password
  • From outside - Internet

You can expose your Jetson Nano to the internet by setting up OpenSSH, but for our use case, there are easier and efficient solutions without the need to configure or maintain a server.

A very nice service provided by https://serveo.net (SSH server) allows you to do port forwarding and get a public URL (or a custom domain name).

#on your jetson, run
ssh -R myalias:22:localhost:22 serveo.net

If you want to connect to Jetson, then all you need to do is

#to ssh to your Jetson Nano, 'user' is your username on Jetson
ssh -J serveo.net [email protected]

Other services like Ngrok or Localhost.run are also useful to make your device/services available online (will be covered in details in another blog post). Here is an overview of my device through SSH

Jetson Screen

Conclusion

Now you have access to the device through SSH (from local network and from Internet). You can disconnect the screen/keyboard and keep only the RJ45 and the power.

In the next steps you may consider installing docker-ce. Also you can setup a Python virtual environments. Since these setups are very common and widely documented, I won’t cover them here.

In following blog posts, I will talk about deploying a Deep Learning application using the Jetson Nano Developer Kit and Nvidia-docker. Stay tuned!