# Parallel/GPU computing lab This lab is the real-world extension of Lab 4 (Running jobs). There, you learned how to request resources and used a simple dummy example — matrix multiplication — to see how threading, multiprocessing, and GPU offload behave when you scale them. Here you repeat that same workflow, but with **real software**: a package that you actually intend to use for your research. Many of you likely already have an idea of what you want to use HPC for. If you already know the software you intend to use, that is great. However, if you have a broad idea, this lab could be even more beneficial as you can investigate different tools for your needs. The aim of this lab is to help you better understand the software that you are going to use for your research, learn how to run it, and eventually learn how to run it well. The software you choose needs to support parallelism (threads or multiple processes) or to be executable on GPUs! Note that if you pick the GPU route, you are required to parallelize your work across **at least two GPUs**. If you're having a hard time choosing software to analyze, there is a list of well-known HPC software at the bottom of the page that you could pick from. **If the software you have in mind is not listed at the bottom of this page, ask the course team whether it is suitable before starting your work — through Slack, at the labs, or by email to mihkel.tiks@ut.ee.** It should be possible to answer all of these questions using the documentation of the software. Many computing centers provide additional information on how to use different software packages. Searching Google for "\ Slurm" often finds these pages, which can be decent guidelines for initial configurations. Answer with specifics — names, values, links. A bare "yes" is not an answer ("no" is sometimes applicable). Where a question gives examples, give *your* concrete values. Feel free to ask questions in Slack if you get stuck, especially on the execution part. ## 1. Software profile **a.** Username on Rocket: **b.** Name of software: **c.** Repository / distribution website (GitHub, homepage, etc.): **d.** Website for documentation: **e.** Briefly describe what problem it solves (1-2 sentences): **f.** How do you get it running on Rocket — an existing module, a container, or building it yourself? Give the specifics (module name, container image, or build system), list its main dependencies, and name the programming languages it is implemented in. ## 2. Choose your path **a.** What kind of parallelism does your workload have (for example, a lot of small independent calculations, one large simulation that does not fit into a single machine, or data-parallel training on batches), and how does the software achieve it — how is the problem split so that many components can work on it at the same time (for example, splitting the data into chunks, decomposing a simulation grid into domains, or running independent tasks concurrently)? This is a general question: the answer is not always simple and the documentation does not always spell it out, but try to answer it as best you can. **b.** Which method do you plan to use for your runs: **threading**, **multiprocessing**, or **GPUs**? **c.** Which of the other two did you consider, and why did you reject them (1-2 sentences)? ## 3. Deep dive on your path Only answer the subsection matching your choice in 2.b. ### Threading (shared memory) **a.** What threading backend does the software use (for example, OpenMP, POSIX threads, TBB)? Is the thread count user-controllable? Name the exact setting or environment variable (for example, `$OMP_NUM_THREADS`) that controls it. **b.** How does your thread count relate to the cores you request from Slurm (`--cpus-per-task`)? What do you expect to happen if the two do not match? ### Multiprocessing (distributed memory) **a.** What is the communication layer between the processes (for example, MPI, Ray, Dask)? What counts as one "task"/rank/process in this software? **b.** How do you control the number of processes (for example, `--ntasks`, `--nodes`), and how is the software launched across them (for example, `mpirun`, `srun`, `torchrun`)? **c.** Does the documentation mention or recommend a specific interconnect (for example, InfiniBand)? ### GPUs **a.** Which GPU platforms does the software support — CUDA (NVIDIA) only, or also ROCm (AMD) and others? Which of these can you use on Rocket's GPU nodes? **b.** How do you select how many and which GPUs the software uses (for example, `CUDA_VISIBLE_DEVICES`, Slurm `--gres`)? **c.** **Required:** you must run on **at least two GPUs**. Which multi-GPU pattern do you plan to use? 1. multiple GPUs in one process, 2. one GPU per process (multiprocessing with GPUs). Describe how your chosen pattern is set up and launched. **d.** Verify your setup: start an interactive session inside your running job (for example, `srun --jobid= --pty bash`) and run `nvidia-smi`. Attach a screenshot of the output showing **both GPUs in use** by your job. **e.** How do your processes/GPUs communicate (for example, NCCL, MPI)? **f.** Which performance-relevant settings matter for your setup? Be specific about: - how many CPU cores you request per GPU (the `--cpus-per-task` to GPU ratio) and why, - the workload size per GPU (for example, batch size, problem size), - any other settings or environment variables needed for the communication (for example, NCCL, MPI). ## 4. The experiment **a.** Tutorials, example scripts, or user communities you relied on (insert links): **b.** Path to batch script: **c.** JobID of a successful run: **d.** Path to the output of the run: **e.** Path to data: **f.** Find or synthesize a workload that takes a measurable amount of time (at least a few minutes), and keep it identical across runs. Run your software **at least 3 times, doubling the relevant resource each time**: - threading → double `--cpus-per-task`, - multiprocessing → double `--ntasks` (or `--nodes`), - GPUs → double the number of GPUs. GPU count is the **only** scaling axis you may change — keep the workload identical between runs, and keep the other resources (CPU cores, memory) proportional to the 1-GPU baseline. A single-GPU baseline run is allowed for the speedup calculation, but your parallel setup must still use at least two GPUs. **g.** Record your runs in the table below (define one throughput metric, such as elements per second, and use it in every row), then fill in the speedup S(N) = T(1)/T(N) and the parallel efficiency E(N) = S(N)/N for each doubling. Did the performance double every time? If not, explain the most likely limiting factor (such as the serial part of the code, communication overhead, or memory bandwidth). | Run | Resources requested | Wall time | Throughput | Speedup S(N) | Efficiency E(N) | | --- | --- | --- | --- | --- | --- | | 1 | | | | — | — | | 2 | | | | | | | 3 | | | | | | Run 1 is the baseline, so its speedup is 1 and its efficiency is 100%. ## 5. Reflection **a.** What was the biggest challenge for you? **b.** What was the most important thing you learned? ## List of well-known HPC software for analysis The course team can help you most with PyTorch and TensorFlow. Some other popular options, which might be difficult if you don't know anything about them, are GROMACS, OpenFOAM, LAMMPS, MATLAB, VASP, and parallel processing packages for R (or any other language).