GPU Exercises #2
Python on the GPU: build an environment on the CPU, then run PyTorch as a GPU batch job.
Go Back to Splash ยปExercises
Time: about 25 minutes. Do GPU Exercises 1 first.
Python is the example here, but everything in this exercise works the same way for other GPU software: prepare on the CPU, then run on the GPU.
Why prepare on the CPU? Installing packages needs the internet, which you get in a normal session with
module load proxy/public. It also takes minutes that would waste a scarce GPU. Do it all in a CPU interactive session first.
Start (or return to) a CPU session in your workshop folder:
srun -p <CPU_PARTITION> --pty bash
cd ~/HPC-Workshop/workdir/GPU
Option A: use the shared environment
Building PyTorch for 20 people at once is slow for everyone. If your instructor has prepared a shared environment, use it and skip to Run the check as a GPU job.
module load Anaconda3/2022.10
source "$(conda info --base)/etc/profile.d/conda.sh"
conda activate <ENV_PATH>
python -c "import torch; print(torch.__version__, torch.version.cuda)"
Option B: build your own environment
This can take 10 to 20 minutes and downloads a couple of gigabytes, so start it now and read on while it runs.
-
Load Python tools and internet access:
module purge module load Anaconda3/2022.10 module load proxy/public source "$(conda info --base)/etc/profile.d/conda.sh" -
Create the environment on Lustre, not in your home directory (environments are large):
ENV_PATH=/mnt/lustre/users/<dep>/<username>/envs/gpu-workshop conda create -y -p $ENV_PATH python=3.11 pip conda activate $ENV_PATH -
Install a CUDA build of PyTorch. Which build matters, because the GPU flavours are different generations. The number after
cumust be no newer than the CUDA version reported bynvidia-smiin Exercise 1, and the build must contain code for your GPU's architecture. Newer GPUs such as the RTX nodes need a newer build than the A40 does (for compute capability 12.0 you need CUDA 12.8 or newer). For example:pip install torch --index-url https://download.pytorch.org/whl/cu128An older build such as
cu121will install without complaint but may fail on a newer GPU withno kernel image is available for execution on the device. See pytorch.org/get-started for the current command for your CUDA version. -
Check the install (on the CPU, so
CUDA availablewill beFalsehere, which is expected):python -c "import torch; print(torch.__version__, torch.version.cuda, torch.cuda.is_available())" python -c "import torch; print(torch.cuda.get_arch_list())"torch.version.cudashould show a version number. If it showsNone, you installed a CPU-only build. The second command lists the GPU architectures this build contains, such assm_86. Your GPU's architecture (from Exercise 1, written the same way: 8.6 issm_86) must be in that list.
Tidy up later: when you have finished with the environment, remove it:
conda env remove -p $ENV_PATH, thenconda clean --all.
Run the check as a GPU job
-
Look at
gpu_check.py. It multiplies two square matrices on the CPU, then on the GPU if one is visible, and prints both times. -
Test it quickly on the CPU, still inside your interactive session, with a small matrix:
python gpu_check.py --n 1024 --repeats 2It will time the CPU and then tell you no GPU is visible. That is the correct answer here.
-
Open
gpu_check.job. Replace<GPU_PARTITION>,<GPU_FLAVOR>,<CUDA_MODULE>and<ENV_PATH>. Because this depends on the GPU architecture, name the flavour (Brighton:--gres=gpu:RTX:1). Notice it also starts a usage log in the background:nvidia-smi --query-gpu=timestamp,utilization.gpu,memory.used --format=csv -l 2 > gpu_usage-$SLURM_JOB_ID.csv & MON_PID=$! python gpu_check.py --n 8192 --repeats 10 kill $MON_PID -
Submit it and watch:
sbatch gpu_check.job squeue --me
Understand the results
When the job finishes, read gpu_check-<jobid>.out and look at the usage log gpu_usage-<jobid>.csv.
- Was CUDA available? Which GPU did PyTorch find? Did the
Build supportsline include your GPU's architecture? If aWARNINGwas printed, the build does not contain code for your GPU: go back to step 3 of Option B. - How much faster was the GPU than the CPU (the speed-up)?
- In the usage log, when did GPU utilisation rise, and how high did it get? What was the GPU doing the rest of the time?
- Change
--nin the job script to 512, then 2048, then 16384 (keep runs short) and resubmit. How does the speed-up change? Why do you think small problems benefit less? CUDA out of memorymeans the matrices did not fit in GPU memory. Roughly how large cannbe for your GPU?
Only one submission at a time please: the 6 GPUs are shared. Wait for a job to finish (or
scancelit) before submitting the next.
Extension: your own Python GPU code
If you have Python code that uses a GPU (PyTorch, TensorFlow, CuPy, Numba, JAX), adapt it:
- Install what it needs into your environment in the CPU session.
- Test a tiny input on the CPU first, if your code supports it.
- Copy
gpu_check.jobtomy_python.job, change the last command to run your script, and keep--timeshort. - Add a line to your script that prints whether it found the GPU, so a failure is obvious from the output.
Carry on in GPU Exercises 4 for a full checklist.
Next: GPU Exercises 3.