Terminal Tricks For Machine Learning Researchers

NVIDIA GPU monitoring

Machine Learning algorithms need plenty of parallel computation and the most common way of doing it lightning-fast is using NVIDIA GPUs. While using NVIDIA GPUs we need to monitor the usage of GPU on the terminal. The easiest way to monitor it is by the following command:

nvidia-smi

In case we want to check GPU usage regularly one can use the following command to refresh the GPU usage information every second:

watch -n 1 nvidia-smi

Advanced Monitoring

When you add the following bash script to the bottom of ~/.bashrc you set watch_gpu as an alias for compact GPU monitoring:

alias watch_gpu="watch -t -n 1 'nvidia-smi | grep -oP \" *[0-9]+MiB \/ *[0-9]+MiB \| *[0-9]+\%\" '"

after adding this command to the ~/.bashrc, use source ~/.bashrc to load the recently updated bashrc. Then when you run watch_gpu in your terminal you will be able to see the following compact GPU usage information on your terminal.

In our case, we have 4 GPUs and as you can see from the figure we have 4 rows. Out of 11178 MiB, we use 0 MiB which means we don't use any of the GPUs yet and all 4 GPUs are free to use. In the last column, the percentage shows how much of the GPU is running now. Observe that GPU memory usage and GPU usage are not the same concepts.

Setting a specific GPU to use

In case we use a multiple GPU machine and we want to utilize specific GPUs for a given task, we need to specify it before running our script with the following command:

export CUDA_VISIBLE_DEVICES=0,1

Here we tell our machine to use only GPUs indexed by 0 and 1.

Server Side

We connect to the server with ssh commands. SSH is known as Secure Shell or Secure Socket Shell, is a network protocol that gives users, particularly system administrators, a secure way to access a computer over an unsecured network. Connecting to a server while mapping a specific port to a local machine port is as simple as adding a couple of words to your command. In the following command, we map port 8888 of the server machine to port 1234 of our local machine.

ssh -L 1234:127.0.0.1:8888 user_name@server_address

This way we can monitor and play with Jupyter notebook, tensorboard, etc useful tools on our local machine while the actual job is done over the server machine.

Copy a file to server:

scp -r ~/some/folder user@server:~/to/where

Copy a file from server to local machine:

scp -r user@server:~/to/where ~/some/folder

You can also download the stuff from an online source utilizing wget command:

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh

You should use the corresponding terminal of the machine. If you want to download online resource into the server then use the command in the server terminal.

Mount a remote folder to a local folder:

In order to mount a folder from the remote server to a local folder, first, create a free folder. Then run following command on your local machine's terminal:

sshfs -o volname=any_name -o follow_symlinks username@server:/remote/folder /local/machine/free_folder

Tmux

Tmux is a terminal multiplier where you can create multiple panes. The main advantage of the "tmux" is that it allows users to run their codes in the background and even if they lose connection to the server, the code will be running. The next time you connect you can check out the results of your code by just attaching the correct tmux session. Another advantage is since the session is an independent terminal session it will keep the settings and environment variables as they are, therefore, you do not need to do manual work over and over again.

First of all, install tmux:

Ubuntu and Debian:

sudo apt install tmux

CentOS and Fedora:

sudo yum install tmux

macOS:

brew install tmux

I have a configuration that I find very useful, which basically converts tmux configuration similar to gnu screen configuration. In order to use the settings;

Create a .tmux.conf file and then copy-paste the following code to the file:

# remap prefix from 'C-b' to 'C-a'

unbind C-b

set-option -g prefix C-a

bind-key C-a send-prefix


# split panes using | and -

bind | split-window -h

bind - split-window -v

unbind '"'

unbind %


# switch panes using Alt-arrow without prefix

bind -n M-Left select-pane -L

bind -n M-Right select-pane -R

bind -n M-Up select-pane -U

bind -n M-Down select-pane -D


# Enable mouse control (clickable windows, panes, resize

set-option -g mouse on


# make scrolling with wheels work

bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"

bind -n WheelDownPane select-pane -t= \; send-keys -M


# reload config file (change file location to your the tmux.conf you want to use)

bind r source-file ~/.tmux.conf


# don't rename windows automatically

set-option -g allow-rename off

set-option -g history-limit 10000

Create a tmux session:

tmux new -s session_name

Attach to an already created session:

tmux a -t session_name

Kill a session:

tmux kill-session -t session_name

Cheatsheet for shortcuts:

  • (ctrl + a) + | :Divide pane

  • (ctrl + a) + - :Divide pane

  • (ctrl + a) + d :Detach session

  • (ctrl + a) + z :Full-screen the current pane / minimize from full screen

  • for further: https://tmuxcheatsheet.com

Bash Profile

Change the appearance of the terminal line:

export PS1="\u@MacBook 🤓 \W $ "

export PS1="\[\033[1;33m\]\u@MacBook 🤓 \W $ \[\033[00m\] "

Add new paths to the PATH:

export PATH="/some/path/:$PATH"