Configuring the Jetson Nano
Background
If you’ve never heard of Nvidia’s Jetson Nano you can think of it as a Raspberry Pi with a built-in GPU; their developer community page has some pretty interesting projects if you’d like to learn more.
Now, you’re only going to get some milage out of the rest of this post if you’ve already setup your Jetson Nano hardware. I set mine up to use the barrel jack for a power source, added a wifi card to the board, and connected it to the Raspberry Pi camera (to collect training data and use for real-time inference).
So, while a number of cool projects with the Jetson Nano exists, I didn’t contribute to any of them so that’s why we’re here. I have this idea that I think could be a pretty amazing applicaiton of deep learning and I want to build out the prototype and what better way to go about it than to create documentation as I go (i.e. fill up this blog with a ton posts). Hopefully, once I get far enough in my endeavors my idea will become more apparent but until then you’ll just have to wait it out and check back in.
Todays Goals - Device Configuartion
-
Mount a swap file for when the compute load gets a bit heavy on the Jetson
-
Get my python setup the way I like it
- Install pip3, virtualenv, pytorch, update my .bashrc for modifications/paths
- Enable SSH‘ing into the device
- Running the monitor isn’t always necessary
- Also, you can mimic working on the cloud this way and practice your bash/terminal commands
Note, all code below can be found in my joys-of-jetson repo.
1. Swap file setup (source code)
You can copy the code below or the repo from git but once you run the script a swap file should be mounted to the Jetson. You’ll need to restart your device for this to take effect.
#!/bin/bash
# 8GB swap file setup
# Source Ref:
# https://support.rackspace.com/how-to/create-a-linux-swap-file/
# TODO Parameterize memory size
set -e
# Swapiness config
# swapiness values: 0-100
# 0 = swap is used when system is completely out of memory
# Higher values enable system to swap idel prcoesses
SWAPINESS=60 # typical value
echo 'Create swap file and formating'
sudo fallocate -l 8G /mnt/8GB.swap # Create swap file
sudo mkswap /mnt/8GB.swap # Format file
sudo swapon /mnt/8GB.swap # Add to filesystem as swap
echo 'Mounting swap file on boot'
# <file system> <mount point> <type> <options> <dump> <pass>
echo '/mnt/8GB.swap none swap sw 0 0' | sudo tee -a /etc/fstab > /dev/null
echo "Adding swapiness, $SWAPINESS, to sysctl.conf"
echo "vm.swappiness=$SWAPINESS" | sudo tee -a /etc/sysctl.conf > /dev/null
# Show swap status
sudo swapon -s
echo '/mnt/8GB.swap should be active above - Restart Device'
2. Python & Pytorch Setup (source code)
Installing the pytorch wheel can take a bit so I suggest killing any non-essential processes (i.e. chromium, emacs, whatever you’re working with just kill it).
And I know this script is a bit chunky but I figure it’s easier to have this configuation in one place then spread out over different scripts, for record keeping/reproducibility/tidy purposes.
You can walk through it line by line if you want since I added comments but it boils down to a few functions for appending files, installing dependencies, and running a python script to check we can import pytorch and that cuda is available.
#!/bin/bash
appendFile(){
echo "$1" | sudo tee -a "$2" > /dev/null
}
appendBashrc(){
FILE="$HOME/.bashrc"
# Check is string exists in ~/.bashrc
if ! grep -q "$1" $FILE; then
appendFile "$1" "$FILE"
source ~/.bashrc
else
echo "$1 exists in $FILE"
fi
}
PYTORCH_VIRTUAL_ENV_NAME="pytorch"
TORCH_URL="https://nvidia.box.com/shared/static/06vlvedmqpqstu1dym49fo7aapgfyyu9.whl"
TORCH_WHL="torch-1.2.0a0+8554416-cp36-cp36m-linux_aarch64.whl"
TORCH_VISION_VERSION="v0.4.0"
# Setup pip and python3 dev
sudo apt update \
&& sudo apt-get -y install python3-pip \
libatlas-base-dev gfortran libhdf5-serial-dev hdf5-tools \
python3-dev
# Install virutal environments
sudo pip3 install virtualenv virtualenvwrapper
# Setting virtual env. paths
appendBashrc "WORKON_HOME=$HOME/.virtualenvs"
appendBashrc 'VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3'
appendBashrc 'source /usr/local/bin/virtualenvwrapper.sh'
# In case source ~/.bashrc not working because of scope
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh
mkvirtualenv "$PYTORCH_VIRTUAL_ENV_NAME" -p python3
workon "$PYTORCH_VIRTUAL_ENV_NAME"
# Install pytorch for Jetson
# Source: https://devtalk.nvidia.com/default/topic/1049071/jetson-nano/pytorch-for-jetson-nano-version-1-3-0-now-available/
wget $TORCH_URL -O $TORCH_WHL
pip3 install numpy $TORCH_WHL && rm $TORCH_WHL
# TorchVision
sudo apt-get -y install libjpeg-dev zlib1g-dev
echo 'Starting TorchVision Build - will take a little bit'
git clone --branch $TORCH_VISION_VERSION https://github.com/pytorch/vision torchvision \
&& cd torchvision && sudo python3 setup.py install && cd ..
# https://stackoverflow.com/questions/23929235/multi-line-string-with-extra-space-preserved-indentation
ASSERT_SCRIPT=$(cat <<-END
#!/usr/bin/python3
import sys
if __name__ == "__main__":
try:
import torch
if torch.cuda.is_available():
sys.exit("true")
except Exception as e:
sys.exit(f"false, str(e)")
END
)
# https://vividcode.io/return-value-from-python-script-to-bash-shell/
INSTALLED=$(python3 -c "$ASSERT_SCRIPT" 2>&1 > /dev/null)
echo "PyTorch imported and cuda available: $INSTALLED"
If after running this script you get a something that
says PyTorch imported and cuda available: false, <Error>
then something went wrong along the way (hopefully, it won’t
but feel free to comment if it does). Other wise
your PyTorch configuration should be ready to go.
3. SSH’ing into Jetson
Finally, since powering an external monitor can be a bit resource intense I’m going to leave you with a bash command to print out the IP address of the Jetson Nano so you can SSH into it and use whatever editor you prefer/have installed (I use emacs).
The command below might not work on your Jeston specifically
but if you have an
Intel Dual Band Wireless-Ac 8265
card installed it might work
just fine; if it doesn’t work you’ll just have to
scour the print out from ifconfig
or ip addr show
for your Nano’s IP.
I commented the command below so you can adjust as needed.
# Show wlan0 portion of IP |
# grep 'inet ' line |
# 'print' the second element from matched 'inet ' grep |
# split string: return 1st element after spliting on delimiter '/'
ip addr show wlan0 | grep 'inet ' | awk '{print $2}' | cut -f1 -d'/'
After you get the IP, go to your work station
terminal and ssh <jeson_user_name>@<jetson_ip>
and
you should be all ready to develop remotely.
The end
Thanks for reading and feel free to comment or suggest corrections.
And here’s a list of sources that helped me bring all of this together: