Skip to content

HPC / CFD Deep Question Bank

All exam-style questions with answers, organised by chapter and difficulty. Use as an active drill: cover the answer, write your own, then check.


Chapter 1 — Course Introduction & HPC Overview

Beginner

  1. What does HPC stand for? High-Performance Computing.
  2. Name two supercomputers. El Capitan, Frontier, JUWELS, Aurora.
  3. OS on every Top500 cluster? Linux.
  4. What is a "core"? One processing unit (ALU + registers) inside a CPU.
  5. Top500 ranks by which benchmark? LINPACK (HPL) in FLOPS.

Intermediate

  1. Define FLOPS and convert 1 PFLOPS to FLOPS. Floating-point operations per second; 1 PFLOPS = \(10^{15}\) FLOPS.
  2. Node vs core? Node = whole computer; core = one processing unit inside its CPU.
  3. State three reasons Linux dominates HPC. Open-source kernel, scriptable shells, modular distributions, POSIX portability.
  4. Difference between simulation and experiment in CFD? Experiments give limited but ground-truth data; simulations give all variables but need validation.
  5. Role of the interconnect in a cluster? Fast inter-node communication for MPI; latency limits strong scaling.

Hard

  1. LES of 5e8 cells × 5e4 steps × 200 ops → total FLOPS? \(5 \times 10^{15}\).
  2. Why do more cores not always help? Amdahl's law: serial fraction limits speed-up to 1/f.
  3. Why are GPUs becoming dominant? Higher FLOPS/W, dense vector compute.
  4. What limits strong scaling? Communication latency vs computation; sub-domain shrinks while messages stay.
  5. Power as Top500 metric? Cooling cost ∝ power; targets push GFLOPS/W.

Very Hard

  1. Algebra of Amdahl plateau. S(N) = 1/(f + (1-f)/N) → 1/f as N → ∞.
  2. 5% serial → max speed-up. 1/0.05 = 20×.
  3. Communication ∝ √N, compute ∝ N — when does communication dominate? When √N × c_comm \(\gtrsim\) N × c_compute, i.e. small per-node work.

Deep Integration

  1. Trace a CFD job from edit to plot. Vim → Git → SSH → SLURM → MPI → rsync → gnuplot.
  2. Why is "scriptability" of Linux more important than "free"? Reproducibility & automation.

Coding/Command

  1. One-liner to print core count. nproc.
  2. Time a program. time ./a.out.

Debugging

  1. Why does parallel program produce different result each run? Race conditions; non-deterministic FP reduction order.
  2. Speed-up decreases beyond 16 cores on a laptop? Hyperthreads share ALUs; cache contention.

Long Written

  1. Discuss IFAS HPC research and sustainable aviation in 250 words. (See Ch. 1 §9.3.)

Chapter 2 — Unix / Linux Basics

Beginner

  1. Who released the Linux kernel? Linus Torvalds, 1991.
  2. What does GNU stand for? GNU is Not Unix.
  3. Licence of Linux kernel? GPLv2.
  4. Two Unix-derived OSes. macOS, Solaris.
  5. Tux? Linux's penguin mascot.

Intermediate

  1. Why was Unix portable? Rewritten in C in 1973.
  2. Who maintains POSIX? IEEE.
  3. Role of init? First user-space process; starts services.
  4. Why clusters use RHEL/Rocky? Long support, ISV certification.
  5. Why is bash the "Bourne-Again Shell"? Successor to Stephen Bourne's sh.

Hard

  1. Two POSIX features. Function API (e.g. fork); shell utilities (grep).
  2. Why Linux ≠ Unix legally? Linux is Unix-like; not derived from AT&T code.
  3. What is glibc? GNU C library; user-side POSIX implementation.
  4. Why does ls work on macOS? Both POSIX-compliant; both ship ls.
  5. Monolithic vs micro-kernel? Linux: drivers in kernel space; Mach: drivers in user space.

Very Hard

  1. How does syscall change privilege (x86_64)? syscall instr → MSR-defined entry → kernel mode.
  2. "Everything is a file" — why useful? Generic syscalls work on devices, sockets, pipes.
  3. Linux vs Hurd? Hurd never finished; GNU userland uses Linux kernel.

Deep Integration

  1. How does Unix philosophy map to Ch. 7? Pipes compose grep/awk/sed.
  2. Why is POSIX still relevant in 2026? Containers, WSL, embedded depend on it.

Coding/Command

  1. Print kernel version. uname -r.
  2. Print current shell. echo $SHELL.

Debugging

  1. ls: command not found despite /bin/ls exists. PATH cleared.
  2. System still boots old kernel after update. GRUB default not updated.

Long Written

  1. Discuss why HPC chooses Linux over BSD/Windows in 250 words. (Ch. 1 §4.4 + Ch. 2 §4.7.)

Chapter 3 — Linux Commands & File Permissions

Beginner

  1. Numeric for rw-r--r--. 644.
  2. Symbolic for 700. rwx------.
  3. Count words in file. wc -w f.
  4. Copy directory. cp -r src dst.
  5. Symbol for home. ~.

Intermediate

  1. Numeric for rwsr-xr-x. 4755.
  2. Numeric for rwxrwxrwt. 1777.
  3. Why chmod 644 cannot run a script. No execute bit.
  4. cp vs mv on same FS. mv just renames inode; cp duplicates data.
  5. ls -ld /tmp output. drwxrwxrwt root root ....

Hard

  1. umask 027 on mkdir. 0777 - 027 = 0750.
  2. List only files. ls -lp \| grep -v '/$' or find . -maxdepth 1 -type f.
  3. Hard link, delete one name. Other still works; ref-count > 0.
  4. cp -r dir1 dir2 if dir2 missing. dir2 created as copy of dir1.
  5. Why rm -i on cluster. Adds confirmation; prevents catastrophic deletes.

Very Hard

  1. -rwsrwsr-T numeric. 7766 (setuid+setgid+sticky+no other-x).
  2. umask differs login vs non-login — why? Different rc files.
  3. rm -rf $undef_var/ danger. Empty var → rm -rf /.

Deep Integration

  1. Why is chmod -R 777 bad on a shared cluster? Anyone can edit; reproducibility lost; security risk.
  2. Why does SLURM need setuid? Helper bins elevate briefly to enforce policy.

Coding/Command

  1. Recursive group-write. chmod -R g+w data/.
  2. Count .cpp. find . -type f -name "*.cpp" \| wc -l.

Debugging

  1. Permission denied running script. chmod +x.
  2. ls > log; ls /missing > log — what's in log? Only stderr appears; merge with 2>&1.

Long Written

  1. Discuss permissions on multi-user HPC in 200 words. (Ch. 3 §9.3.)

Chapter 4 — bashrc, SSH, Remote Workflows

Beginner

  1. Default SSH port. 22.
  2. File listing your authorized public keys. ~/.ssh/authorized_keys.
  3. One-shot file copy command. scp.
  4. Incremental sync command. rsync.
  5. & at end of command. Run in background.

Intermediate

  1. Why ed25519 over RSA? Smaller, faster, modern.
  2. Permission for ~/.ssh/id_ed25519. 600.
  3. Where do aliases go for persistence? ~/.bashrc.
  4. source vs run. source modifies current shell.
  5. 2>&1 plain English. Send stderr where stdout points.

Hard

  1. ssh -L 8888:cn01:8888 user@gw. Local-port forward localhost:8888 ↔ gateway tunnel ↔ cn01:8888.
  2. Why does tmux survive disconnection? Server process owns the pty.
  3. Mode 777 on ~/.ssh. SSH refuses keys for safety.
  4. ~/.ssh/known_hosts. Stores trusted server fingerprints; detects MITM.
  5. rsync src/ dst/ vs rsync src dst/. Trailing slash = contents only.

Very Hard

  1. Why TOFU weakness for SSH host keys? First-contact MITM possible; mitigate via SSHFP DNS or CA.
  2. Agent forwarding (ssh -A) trade-off. Convenience vs forwarding-host compromise.
  3. Why scp blocks but rsync resumes? scp has no chunking/state; rsync rebuilds via checksums.

Deep Integration

  1. Map SSH ops to CFD workflow. ssh login → tmux → rsync push → sbatch → tmux detach → rsync pull.
  2. Why disable password auth on cluster? Stops brute-force; key-based audit-friendly.

Coding/Command

  1. Mirror with delete. rsync -avzP --delete ~/work/ cluster:~/work/.
  2. Bash function tunneling Jupyter. jup(){ ssh -L 8888:$1:8888 cluster; }.

Debugging

  1. Permission denied (publickey) despite key. Wrong perms / key not in agent / not in authorized_keys.
  2. scp: not found on cluster. OpenSSH ≥9 disabled scp; use scp -O or rsync/sftp.

Long Written

  1. Daily CFD workflow with SSH/rsync/tmux/SLURM in 250 words.

    A CFD researcher's day starts locally: edit the case (Vim), commit (Git), push. Then ssh hpc — public-key authentication, configured once via ssh-keygen, ssh-copy-id, and a ~/.ssh/config Host block, makes this a two-second, password-free step. On the login node, tmux new -s work creates a session that will survive any disconnection; inside it, git pull fetches today's changes and module load gcc/12 openmpi/4.1 restores the toolchain. Input data moves with rsync -avzP laptop:case_A/ $WORK/case_A/ — incremental, compressed, resumable, so re-syncing a 50 GB case after a small change transfers only the changed blocks. The job itself is never run on the login node: sbatch run.sbatch hands it to SLURM, squeue -u $USER shows PENDING→RUNNING, and the script's #SBATCH lines fix nodes, tasks, walltime and partition. While the solver runs, the researcher detaches (Ctrl-b d), closes the laptop, and later re-attaches with tmux a -t work — the shell, history and monitoring loops are exactly where they were left. When sacct reports COMPLETED, results return with rsync -avzP $WORK/case_A/results/ laptop:results/ — again incremental, so daily harvesting stays cheap. Post-processing (awk → gnuplot) can run remotely, sending back only PNGs. The pattern to stress in the exam: SSH provides the secure channel everything else rides on; rsync minimises data motion; tmux decouples session lifetime from connection lifetime; SLURM decouples computation from the login node. Four tools, one principle each — together they make remote HPC feel local.

Chapter 5 — Vim & Command-Line Editing

Beginner

  1. Save and quit. :wq (or ZZ).
  2. Discard. :q!.
  3. Copy line. yy.
  4. Delete 5 lines. 5dd.
  5. Undo. u.

Intermediate

  1. ci". Change inside quotes.
  2. >aP. Indent a paragraph.
  3. Replace foo→bar lines 5–10. :5,10s/foo/bar/g.
  4. Search backwards. ?Re.
  5. Open Makefile in vsplit. :vsp Makefile.

Hard

  1. Whole-word replace. :%s/\<Re\>/Reynolds/g.
  2. Repeat last :s. &.
  3. Yank function body. Cursor in body, ya{.
  4. Append ; to every line. :%s/$/;/.
  5. Comment out lines 5–20. :5,20s/^/\/\//.

Very Hard

  1. Edit on 200 buffers. :bufdo %s/foo/bar/ge \| update.
  2. Sort selected lines numerically. Select V, :'<,'>!sort -n.
  3. Reformat paragraph to 80 cols. gq (with set textwidth=80).

Deep Integration

  1. Batch-edit 50 SLURM scripts. vim *.sbatch; :argdo %s/--time=2/--time=4/ge \| update.
  2. Why Vim over VS Code on HPC? Works over SSH; pre-installed; low memory.

Coding/Command

  1. Macro to wrap line in if(true){…}. qa I if(true) { <Esc>A } <Esc>q then @a.
  2. <F5> mapping to compile + run C++. See Ch. 5 §6.4.

Debugging

  1. :s/foo/bar/g only 1 match. Need %: :%s/foo/bar/g.
  2. :w read-only. :w! or :w !sudo tee %.

Long Written

  1. Discuss Vim grammar's productivity in 250 words.

    Vim's productivity comes from treating editing as a language, not a menu. Commands compose as [count][operator][motion]: d (delete), c (change), y (yank), > (indent) are verbs; w, e, $, }, G, i", a{ are motions and text objects. Learning m operators and n motions yields m·n commands — 8 verbs × 10 motions = 80 edits from 18 memorised pieces. d2w deletes two words, ci" changes inside quotes, y} yanks a paragraph: each reads like a sentence, and once one new motion is learned it instantly works with every verb. Three multipliers sit on top. The dot command . repeats the last change, turning a one-off fix into a keystroke-per-occurrence sweep. Registers give named clipboards ("ayy, "ap), with "_ discarding deletions so a prepared yank survives. Macros record any keystroke sequence into a register (qa … q) and replay it (@a, 5@a, or :g/pat/normal! @a across a whole file) — a disposable program written by demonstration, ideal for reformatting hundreds of SLURM log lines or case-file entries. Ex commands scale the same grammar to file ranges: :5,20s/^/# / comments a block, :argdo %s/Re=1000/Re=5000/ge | update edits fifty buffers. On clusters this matters doubly: Vim is always installed, runs over SSH without a GUI, and starts instantly. The exam-worthy conclusion: modal editing spends keystrokes on structure rather than cursor travel, and its combinatorial grammar means capability grows multiplicatively while learning grows additively.

Chapter 6 — Regex & Globbing

Beginner

  1. *.txt in shell. All files ending .txt.
  2. ^abc regex. Lines starting abc.
  3. Glob for one char. ?.
  4. POSIX class for digits. [[:digit:]].
  5. Regex for word + space. [[:alpha:]]+.

Intermediate

  1. List .h .cpp in dir-1+dir-2. ls {dir-1,dir-2}/*.{h,cpp}.
  2. Loose IPv4 regex. ([0-9]{1,3}\.){3}[0-9]{1,3}.
  3. Replace tabs with 4 spaces (sed). sed 's/\t/ /g'.
  4. Whole-word Re. \<Re\> (BRE/ERE) or \bRe\b (PCRE).
  5. Glob hidden files. .[!.]*.

Hard

  1. No-foo-no-bar lines (PCRE). ^(?!.*(foo|bar)).*$.
  2. Phone with optional country code. (\+[0-9]+ )?[0-9]{3}-[0-9]{3}-[0-9]{4}.
  3. Negate glob. extglob !(pattern).
  4. Replace SciNot by 0.0. sed -E 's/[0-9]*\.[0-9]+[eE][+-]?[0-9]+/0.0/g'.
  5. Date YYYY-MM-DD regex. [0-9]{4}-[0-9]{2}-[0-9]{2}.

Very Hard

  1. ls *.txt faster than find . -name "*.txt". Glob expanded once via readdir; find recurses.
  2. Strict IPv4 regex. ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|...).
  3. Negate glob. shopt -s extglob; ls !(tmp*).

Deep Integration

  1. Pipeline to print files matching regex. grep -lE 'PATTERN' *.log.
  2. Why regex101.com first? Test before destructive sed -i.

Coding/Command

  1. Find today's logs and grep ERROR. find . -mtime -1 -type f -name '*.log' -exec grep -l ERROR {} +.
  2. Vim whole-word replace all open buffers. :bufdo %s/\<oldName\>/newName/ge \| update.

Debugging

  1. grep "(foo|bar)" f no match. BRE: parens literal; use -E.
  2. ls *.[ch] empty. No matching files; shopt -s nullglob.

Long Written

  1. Regex+glob in HPC log analysis pipeline (250 words).

    Globs and regexes divide the labour in every HPC log pipeline: the shell's glob chooses which files, a tool's regex chooses which text inside them. They look similar but differ in meaning (* = any string in a glob, but = zero-or-more of the previous atom in a regex) and in who expands them — the shell substitutes globs before the program ever runs, while grep/sed/awk apply regexes to file content. A realistic sweep: 200 cases live in case_*/; ls case_*/run.log (glob) enumerates the logs. Health check: grep -lE "diverg(ed|ing)|nan|inf" case_*/run.log — the glob fans out to 200 paths, the ERE alternation flags sick runs, -l prints only filenames for the rerun list. Extraction: grep -hoE "residual=[0-9.eE+-]+" case_042/run.log isolates numeric fields, or awk '/^Time =/ {print $3, $7}' converts a verbose log into two-column plot data. Bulk repair uses sed with a captured group: sed -i -E 's/^(Re *= *)1000\b/\15000/' case_*/in.dat — the glob selects the files, the backreference keeps the untouched part, -i edits in place (test without -i first). Recursive selection upgrades to shopt -s globstar; **/*.log, and stricter file choice can move into find -name "*.log" -mtime -1 when age or size matters. The trap to name: quoting — find . -name "*.log" must protect the pattern from shell expansion, the exact opposite of the ls case. One line of exam summary: globs name files, regexes match text; the pipeline glob → grep → sed/awk is HPC's standard log-analysis machine.

Chapter 7 — Linux Text Tools

Beginner

  1. All .txt in ~. find ~ -type f -name "*.txt".
  2. Count lines with ERROR. grep -c ERROR log.
  3. Replace first foo→bar per line. sed 's/foo/bar/' f.
  4. Print 2nd CSV field. awk -F, '{print $2}' f.
  5. Diff two files. diff a b.

Intermediate

  1. Files >100 MB. find . -size +100M.
  2. Replace all foo→bar in place. sed -i 's/foo/bar/g' f.
  3. Sum column 3. awk '{s+=$3} END{print s}' f.
  4. First match per file. grep -m1 PAT *.log.
  5. Unique departments. awk -F, 'NR>1{print $3}' f \| sort -u.

Hard

  1. CSV with quoted commas — parsing? awk -v FPAT='([^,]+)|("[^"]+")'.
  2. Median of column. awk '{a[NR]=$1} END{n=asort(a); ...}'.
  3. Replace IPs with [redacted]. sed -E 's/[0-9]{1,3}(\.[0-9]{1,3}){3}/[redacted]/g'.
  4. 5 longest lines. awk '{print length, $0}' f \| sort -nr \| head -5.
  5. Diff huge files: just summary. diff -q a b.

Very Hard

  1. awk pivot by dept & gender. awk -F, 'NR>1{c[$3,$5]++} END{for(k in c) print k,c[k]}'.
  2. sed conditional. sed -E '/^Re/s/=[0-9]+/=5000/'.
  3. find avoiding node_modules. find . -name node_modules -prune -o -type f -print.

Deep Integration

  1. Find cout not followed by endl in .cpp. grep -rEn 'cout[^;]*;[^l]*' --include='*.cpp' ..
  2. Top-10 directories by size. du -sk * \| sort -nr \| head -10.

Coding/Command

  1. awk: NR>1 && salary>50000. awk -F, 'NR>1 && $4>50000 {print $1,$2,$3}' f.
  2. sed swap Last_First → First_Last. sed -E 's/([A-Za-z]+)_([A-Za-z]+)/\2_\1/'.

Debugging

  1. awk prints empty for CSV. Need -F,.
  2. sed 's/(foo|bar)/X/g' literal. Need -E.

Long Written

  1. sed vs awk discussion in 250 words.

    sed and awk are both stream processors, but they answer different questions. sed is a stream editor: it reads one line into the pattern space, applies editing commands — overwhelmingly s/pattern/replacement/ — auto-prints, and moves on. It is the tool for mechanical text surgery: substitutions with backreferences (s/^(Re *= *)1000/\15000/), deletions (/^#/d), line-range edits (5,10s/^/# /), in-place bulk changes across case files with -i.bak. It has no arithmetic and no real variables; its power is regex-driven rewriting at pipeline speed. awk is a small programming language over structured text: each record (line) is auto-split into fields $1..$NF, patterns guard actions (pattern { action }), and BEGIN/END blocks frame the run. It owns every task involving columns or numbers: awk '{s+=$2} END{print s/NR}' for a mean, $5=="PD" {n++} for conditional counts, associative arrays (sum[$2]+=$3) for per-group totals, printf for formatted tables. Choosing between them is exam-simple: if the job is "change this text into that text", sed; if it is "select, compute or reformat by columns", awk; if both, chain them — grep narrows, sed cleans, awk computes, sort|uniq -c summarises. In CFD practice sed rewrites in.dat parameters for sweeps, while awk turns solver logs into residuals.dat for gnuplot. Mention the models to score theory marks: sed's pattern-space cycle versus awk's record/field model — one edits a stream, the other programs over it.

Chapter 8 — Shell Scripting

Beginner

  1. Make script executable. chmod +x s.sh.
  2. Print first arg. echo $1.
  3. Number of args. $#.
  4. Exit success. exit 0.
  5. Array length. ${#A[@]}.

Intermediate

  1. Test file exists. [ -f f ].
  2. Loop *.cpp. for f in *.cpp; do ...; done.
  3. Read input. read -p "?: " ans.
  4. Subshell. ( cd dir; ls ).
  5. Capture cmd output. x=$(cmd).

Hard

  1. cd dir; cmd vs (cd dir; cmd). Subshell scope.
  2. Replace .txt with .bak. for f in *.txt; do mv -- "$f" "${f%.txt}.bak"; done.
  3. getopts with combined flags. See Ch.8 §4.12.
  4. Predict (( 0 )). Exit status 1.
  5. Source vs run. . file.sh runs in current shell.

Very Hard

  1. for f in $(ls) worse than for f in *. Word splitting on filenames with spaces.
  2. set -e pitfalls in pipes. Need pipefail for middle-of-pipe errors.
  3. Memoization in bash. Associative arrays.

Deep Integration

  1. Combine awk + bash for failed cases. awk '/FAIL/{print $1}' results \| xargs -n1 ./rerun.sh.
  2. Trap to clean tmp on Ctrl-C. trap 'rm -f "$tmp"' EXIT INT TERM.

Coding/Command

  1. Sum file sizes in dir. du -sb "$1" \| cut -f1.
  2. Squares 1..10. for i in {1..10}; do echo $((i*i)); done.

Debugging

  1. if [ $x = "yes" ] fails empty. Quote: [ "$x" = "yes" ].
  2. for f in *.cpp; do ... with no matches. shopt -s nullglob or guard.

Long Written

  1. Walk through extended backup-data.sh in 250 words.

    The extended backup script is a template for defensive shell tooling. It begins with #!/bin/bash and a USAGE function that prints the call syntax and exits non-zero — errors are loud, not silent. Option parsing uses getopts ":vs": the loop consumes -v (VERBOSE=1) and -s (SYNC=1), the leading colon selects silent error handling so an invalid flag lands in the ? case, which calls USAGE. The essential line after the loop is shift $((OPTIND-1)): it discards the parsed options so $1/$2 become the real positional arguments, SOURCE and DEST. Validation follows: [ -d "$SOURCE" ] && [ -d "$DEST" ] guarantees both directories exist before anything destructive; the quotes keep space-containing paths intact. The action block is a two-level branch. With SYNC=1 the transfer is rsync -aP (archive mode preserves permissions/timestamps, -P resumes and shows progress) — incremental, so repeated backups copy only changes; verbose adds -v. Without sync it falls back to cp -r, again with -v when requested. Each branch checks the command's exit status ($?) and reports success or failure, so the caller — a human or a cron job — gets a trustworthy return code. The design points to name in the exam: getopts+shift is the canonical CLI pattern; validation before action; rsync over cp for repeated data movement; quoting everywhere; explicit exit codes. In CFD daily life this exact skeleton ships results from $WORK to a project share — the exercise is a rehearsal for production cluster scripts.

Chapter 9 — Gnuplot

Beginner

  1. Plot sin(x). plot sin(x).
  2. Add title. set title "..."; replot.
  3. Save PNG. set terminal png; set output 'x.png'; replot.
  4. Plot col 1 vs 3. using 1:3.
  5. Legend top-right. set key right top.

Intermediate

  1. Log y axis. set logscale y.
  2. Two curves on one plot. plot 'a' u 1:2, 'b' u 1:2.
  3. Red dashed thick. lt 2 lw 3 lc rgb "red" dt 2.
  4. Error bars. using 1:2:3 with yerrorbars.
  5. 2×2 multiplot. set multiplot layout 2,2 ....

Hard

  1. Fit a*exp(-b*x). f(x)=a*exp(-b*x); fit f(x) 'd' via a,b.
  2. Twin y-axis. set y2tics; plot ... axes x1y2.
  3. Histogram. smooth frequency with boxes.
  4. Conditional colour. lc variable based on column.
  5. 3-D surface. splot 'mesh' u 1:2:3 with pm3d.

Very Hard

  1. awk → gnuplot in one script. See Ch. 9 §6.8.
  2. Animate frames into GIF. Bash loop + convert -delay.
  3. LaTeX-ready labels. set terminal cairolatex eps.

Deep Integration

  1. Auto-plot every case. §7 + 6.7.
  2. gnuplot vs Excel for HPC. Reproducible, scriptable, terminal output.

Coding/Command

  1. Plot column 1 in ms. plot 'd' using ($1*1000):2 with lines.
  2. Horizontal line at 1e-6. set arrow from graph 0,first 1e-6 to graph 1,first 1e-6 nohead lt 0.

Debugging

  1. Plot CSV nothing. set datafile separator ",".
  2. PNG empty. Forgot replot after set terminal png.

Long Written

  1. gnuplot as HPC postprocessor in 250 words.

    gnuplot fits HPC because it is text-driven, scriptable and headless — the same reasons Linux fits HPC. A plot is a short program: set terminal/output, titles, ranges, set logscale y for residuals spanning ten decades, then plot 'residuals.dat' using 1:2 with linespoints. Because it is a program, it is reproducible: the .gp script lives in Git next to the solver, and anyone can regenerate the figure from raw data — impossible to guarantee with GUI spreadsheets. It composes with the shell: awk extracts iter residual pairs from a noisy solver log, a heredoc or gnuplot -e "datafile='...'" parameterises the script, and a bash loop renders one PNG per case — two hundred convergence plots from an overnight sweep with no clicks. It runs on the cluster itself, so gigabyte logs never cross the network; only kilobyte PNGs come home (compute where the data lives). Beyond line plots it covers the scientific needs: multiplot grids for dashboards, error bars (using 1:2:3 with yerrorbars), 3-D splot ... with pm3d, and least-squares fitting — fit f(x) 'd' via a,b,c minimises the residual sum of squares with Levenberg–Marquardt and reports parameter errors in fit.log, turning a grid-convergence study into a slope read straight off a log-log line. Terminals export raster PNG for slides and vector pdfcairo for papers. Note the 2026 caveat: the dedicated lecture was dropped, but the workflow — awk → gnuplot → PNG — remains the canonical, exam-quotable way HPC results become figures.

Chapter 10 — Git

Beginner

  1. Init. git init.
  2. Stage. git add file.
  3. Commit. git commit -m "msg".
  4. Log. git log.
  5. Clone. git clone url.

Intermediate

  1. Create+switch branch. git switch -c x.
  2. Merge x into main. git checkout main; git merge x.
  3. Delete branch. git branch -d x.
  4. Add remote. git remote add origin url.
  5. First push. git push -u origin main.

Hard

  1. Undo last commit, keep staged. git reset --soft HEAD~1.
  2. Squash 3 commits. git rebase -i HEAD~3 then s lower two.
  3. Restore deleted file. git restore -- file.
  4. Cherry-pick commit. git cherry-pick <hash>.
  5. Log of file. git log -- solver.cpp.

Very Hard

  1. FF vs 3-way merge. FF linear; 3-way merge commit with two parents.
  2. Recover deleted branch. git reflog → git branch x <hash>.
  3. git bisect. Binary search through history for bad commit.

Deep Integration

  1. Tag + reproducibility on cluster. git tag v1.0-paper; git push --tags.
  2. Why rebase shared branch is bad. Rewrites history; teammates' fetches break.

Coding/Command

  1. Stage all .cpp and commit. git add '*.cpp'; git commit -m "...".
  2. Show README changes last 5 commits. git log -p -5 README.md.

Debugging

  1. Updates were rejected. git pull --rebase then push.
  2. PAT 401. Token expired or missing scope.

Long Written

  1. GitFlow vs GitHub Flow for HPC team in 250 words.

    GitFlow and GitHub Flow are two branching policies on the same Git machinery. GitFlow is ceremonial: a permanent develop branch collects features; feature/* branches merge into develop; releases get their own release/* stabilisation branches, tagged into main; emergencies go through hotfix/*. GitHub Flow is minimal: main is always deployable; every change is a short-lived branch off main, pushed early, reviewed as a Merge/Pull Request with CI, merged, deleted. For a research CFD team, the trade-offs are concrete. GitFlow's release branches suit software that ships versioned artefacts to external users — a solver released as v2.1 to other institutes, needing long-term support branches and back-ported hotfixes. Its cost is bookkeeping: two long-lived branches, more merges, more conflict surface — heavy for a five-person group where "release" means "the tag used in the paper". GitHub Flow matches how research code actually evolves: small increments, continuous integration running the build plus regression cases on every MR, main always able to reproduce yesterday's results. Reproducibility comes not from release branches but from tags: git tag -a v1.0-paper pins the exact commit behind every figure, and the cluster job clones that tag. A sensible recommendation to defend in the exam: default to GitHub Flow (simplicity, CI-guarded main, tags for papers) and borrow GitFlow's release branch only when the group must maintain an old shipped version in parallel. The meta-point: branching models are policy, not technology — pick the lightest policy that protects main and preserves provenance.

Chapter 11 — C++ Basics

Beginner

  1. Compile hello. g++ hello.cpp -o hello.
  2. Print "hi". std::cout << "hi" << std::endl;.
  3. Declare int. int a=5;.
  4. Address of a. &a.
  5. Pointer to a. int *p=&a;.

Intermediate

  1. Loop length 5. for(int i=0;i<5;++i) ....
  2. Pass by reference. void f(int& a).
  3. Class with public method. See Complex.
  4. Init list. T():a(0){}.
  5. using namespace std bad in headers. Name pollution.

Hard

  1. Why call-by-value doesn't modify caller? Copy.
  2. int *p; *p=5;. Uninitialised pointer.
  3. delete vs delete[]. Single object vs array.
  4. Why endl slow. Flushes buffer.
  5. Returning class by value. Uses copy/move.

Very Hard

  1. Why const Field&? Avoid expensive copies.
  2. Stack vs heap. Auto vs new/delete; lifetime.
  3. Forgot ; after class. Cascading errors.

Deep Integration

  1. Pointer arithmetic ↔ SIMD vectorisation. Contiguous memory, stride 1.
  2. RAII vs new/delete. Constructor acquires, destructor releases — exception-safe.

Coding/Command

  1. swap by reference. void swap(int&a,int&b){int t=a;a=b;b=t;}.
  2. Add operator+ to Complex. See Ch. 11 §9.7.

Debugging

  1. p uninit when reading. p=&a first.
  2. c.x=5 private. Use accessor or make public.

Long Written

  1. Why HPC kernels avoid copying — by-ref vs ptr (250 words).

    Copying is the silent performance killer in HPC, because moving bytes costs more than computing on them. A CFD field of 10⁸ cells with four doubles per cell is ≈3 GB; passing it by value copies 3 GB through a memory system delivering perhaps 400 GB/s — tens of milliseconds per call, repeated every time-step, plus doubled peak RAM that can push a node into OOM. Call-by-value also defeats caches: the copy evicts the hot working set. Hence kernels pass big objects by reference (void update(Field& f)) or by pointer (void update(Field* f)), both costing eight bytes regardless of payload. References are the C++ default: they cannot be null, cannot be reseated, need no dereference syntax, and const Field& documents read-only intent while letting the compiler optimise. Pointers remain necessary where nullability ("no boundary field attached"), reseating, raw arrays decayed from C interfaces, or MPI buffers (MPI_Send(&x, …)) are involved. The same economy drives the wider stack: swap-by-pointer exchanges array ownership instead of contents; std::vector moves steal the internal pointer in O(1); range-for uses const auto& to avoid per-element copies; MPI halo exchange ships only the ghost layer, never the sub-domain. The rule to state: copy scalars, reference aggregates; make read-only intent const&; reach for pointers only when null/reseat/C-API semantics demand them. Then quantify once — 3 GB versus 8 bytes — and the exam answer writes itself: in HPC, data motion, not arithmetic, is the budget.

Chapter 12 — Build Process

Beginner

  1. Default executable name. a.out.
  2. Include path flag. -I path.
  3. Library path. -L path.
  4. Link math. -lm.
  5. make clean typically. Remove generated.

Intermediate

  1. Compile single to .o. g++ -c file.cpp.
  2. Link two .o. g++ a.o b.o -o prog.
  3. Build static lib. ar rcs libx.a a.o b.o.
  4. Build shared lib. g++ -shared -fPIC -o libx.so a.cpp b.cpp.
  5. List symbols. nm libx.a.

Hard

  1. Why -fPIC for shared. PIC: relative addressing for variable load addresses.
  2. Why make rebuilds only changed. Timestamp comparison.
  3. LD_LIBRARY_PATH. Runtime lib search dirs.
  4. -L vs -l. Path vs library name.
  5. rpath. Embedded run-time lib paths.

Very Hard

  1. ldd shows not found. Missing .so in search paths.
  2. Find heavy header. g++ -H -c ….
  3. make -j$(nproc) faster. Parallel build.

Deep Integration

  1. Header guards + templates + inline. Templates/inline must be in headers; guards prevent dup non-inline non-template defs.
  2. CMake adoption in CFD. Portability + dependencies + tests + install.

Coding/Command

  1. Makefile rule for Complex.h-aware .cpp→.o. See Ch.12 §6.6.
  2. CMakeLists for same project. See harder version.

Debugging

  1. Makefile:5: missing separator. Use TAB.
  2. undefined reference to add(int,int). Forgot to compile/link add.cpp.

Long Written

  1. Make vs CMake for 100-file CFD project (250 words).

Chapter 13 — Debugging

Beginner

  1. Debug compile flag. -g.
  2. Start gdb. gdb ./prog.
  3. Set breakpoint. break 10.
  4. Run. run.
  5. Print var. print x.

Intermediate

  1. Step into vs over. step / next.
  2. Print 5-element array. p *arr@5.
  3. Run to function end. finish.
  4. Show stack. backtrace.
  5. Detect leaks. valgrind --leak-check=full.

Hard

  1. <optimized out>. Compiled with -O2+.
  2. Pause when i==100. watch i; cond N i==100.
  3. Inspect register. info registers; p $rax.
  4. Set var from gdb. set var x = 5.
  5. Attach to process. gdb -p <pid>.

Very Hard

  1. Reverse-debug. record full; reverse-step.
  2. Debug optimized build. -O2 -g -fno-omit-frame-pointer.
  3. Debug MPI rank. mpirun gdb or attach to PID.

Deep Integration

  1. Sanitizer in CI. Build with ASan; fail on errors.
  2. Why leaks bad in CFD jobs. OOM; growing per iteration.

Coding/Command

  1. One-liner with ASan. g++ -O1 -g -fsanitize=address prog.cpp && ./a.out.
  2. gdb finding debug03 NULL deref. See Ch.13 §6.3.

Debugging

  1. No core file. ulimit -c unlimited.
  2. valgrind "uninitialised value". Use --track-origins=yes.

Long Written

  1. gdb on debug05 step-by-step (250 words).

    debug05.cpp wraps is_prime in a loop printing primes up to 31; the exercise is to verify the logic live rather than guess. Step 1: build for debugging — g++ -O0 -g debug05.cpp -o d5; -g embeds source mapping, -O0 stops the optimiser from dissolving variables into <optimized out>. Step 2: gdb ./d5, then break is_prime and run — execution pauses at the first call. Step 3: inspect the call: print num shows the argument (first call: 1, since the loop passes i+1); info locals shows prime initialised true. Step 4: trace the guard: next over if (num < 2) and watch the early return — finish runs to the end of the function and prints the return value, false for 1, confirming 1 is correctly excluded (and exposing the variant bug return prime; if it printed true). Step 5: probe a composite: condition 1 num==9, continue; inside, display i and display prime, then next repeatedly — at i=3, 9 % 3 == 0 flips prime to false; note the loop still walks to i=8, a correctness-irrelevant inefficiency worth one comment (break would fix it). Step 6: check the boundary: the caller tests up to i+1 == 31, so condition 1 num==31, continue, finish → true, 31 printed — the <=30 loop is intentional, not off-by-one. Step 7: delete breakpoints; continue and compare the full output 2 3 5 7 … 31. The transcript — break, run, print, next/finish, conditional breakpoints, display — is exactly the reusable gdb vocabulary the written exam asks you to demonstrate.

Chapter 14 — Parallelization

Beginner

  1. OpenMP for? Shared-memory.
  2. MPI for? Distributed-memory.
  3. MPI compile. mpic++ -O2 a.cpp -o a.
  4. Run with 4 ranks. mpirun -n 4 ./a.
  5. Default communicator. MPI_COMM_WORLD.

Intermediate

  1. Amdahl. S=1/(f+(1-f)/N).
  2. rank vs size. ID vs total.
  3. Why reduction? Avoid race.
  4. Datatype double. MPI_DOUBLE.
  5. Tag. Message label for matching.

Hard

  1. Send/Recv size mismatch. Error or hang.
  2. Blocking vs non-blocking. Returns when safe vs immediately + Wait.
  3. MPI_Allreduce. Reduce + broadcast.
  4. Why halo cells? Avoid per-cell communication.
  5. schedule(dynamic) better when? Variable iteration cost.

Very Hard

  1. Why more ranks slow down beyond a point? Strong-scaling: communication > compute.
  2. Avoid load imbalance. ParMETIS partitioning by cost.
  3. MPI_Sendrecv vs separate. Atomic exchange; deadlock-free for pairwise.

Deep Integration

  1. MPI + OpenMP + GPU. MPI between, OpenMP within node, OpenACC/CUDA on GPU.
  2. Why GPU CFD still needs MPI. Multi-GPU multi-node.

Coding/Command

  1. OpenMP doubles array.

    #pragma omp parallel for
    for (int i = 0; i < N; ++i) a[i] *= 2;
    
    Each iteration touches a distinct element, so there is no shared write → no race and no reduction needed; compile with -fopenmp and control threads via OMP_NUM_THREADS.
    #pragma omp parallel for
    for(int i=0;i<N;++i) a[i]*=2;
    

  2. Broadcast int. MPI_Bcast(&x,1,MPI_INT,0,MPI_COMM_WORLD);.

Debugging

  1. Hang on 2 ranks. Both Recv first; reorder or Sendrecv.
  2. Race wrong sum. Add reduction(+:sum).

Long Written

  1. Why hybrid MPI+OpenMP dominates CFD (250 words).

    Hybrid programming mirrors the hardware. A cluster is distributed memory between nodes and shared memory within a node; MPI matches the first, OpenMP the second. Pure MPI on a 128-core node means 128 ranks: each carries its own halo copies, buffers and runtime state, so memory per node balloons and the halo surface multiplies — communication grows with rank count even though the physics did not change. Hybrid runs a few ranks per node (often one per NUMA domain or per GPU) and lets OpenMP threads share that rank's arrays directly: intra-node "communication" becomes plain loads/stores, halos exist only at true node boundaries, and per-rank memory overhead drops by the thread count. Collectives also cheapen — MPI_Allreduce over 8 ranks × 16 threads synchronises 8 endpoints, not 128. The canonical CFD structure follows: domain decomposition assigns one sub-domain per rank (--ntasks-per-node), #pragma omp parallel for (with reductions) spreads cell loops over --cpus-per-task threads, non-blocking Isend/Irecv overlap halo exchange with interior computation, and OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK keeps SLURM and the runtime consistent. Load balance improves too: threads self-balance inside a rank (schedule(dynamic)), softening partitioning imperfections that pure MPI freezes in. The model extends naturally to accelerators — MPI between nodes, OpenMP/offload or CUDA within — which is precisely JUPITER's Grace-Hopper design. Exam summary sentence: hybrid wins because it sends messages only where memory is actually distributed and shares memory wherever it truly is shared — matching the machine beats fighting it.

Chapter 15 — HPC Cluster

Beginner

  1. Where jobs run. Compute nodes.
  2. List software. module avail.
  3. Submit job. sbatch script.sh.
  4. See queue. squeue.
  5. Cancel job. scancel ID.

Intermediate

  1. Reserve interactively. srun --pty --nodes=1 bash.
  2. Heavy I/O location. $WORK.
  3. OpenMP threads from SLURM. export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK.
  4. Job 99 details. scontrol show job 99.
  5. Module file-search. module spider <name>.

Hard

  1. Job dependencies. sbatch --dependency=afterok:<id>.
  2. ntasks vs cpus-per-task. MPI ranks vs OpenMP threads.
  3. Pin processes to cores. --cpu-bind=cores / OMP_PROC_BIND=true.
  4. Why module purge first. Reproducible environment.
  5. sinfo shows what. Partition names + limits.

Very Hard

  1. sbatch over nohup. Scheduler accounting + isolation + restart.
  2. Lustre stripes. File split across OSTs for parallel I/O.
  3. Why checkpoint long jobs. Walltime kill recovery.

Deep Integration

  1. Git + module + SLURM. Ch.15 §7.
  2. Why record module list. Reproducibility.

Coding/Command

  1. srun for 4 ranks 1 hour gpu partition. srun --pty --partition=gpu --nodes=1 --ntasks=4 --gres=gpu:1 --time=1:00:00 bash.
  2. Wait until own jobs end. until [ -z "$(squeue -h -u $USER)" ]; do sleep 60; done.

Debugging

  1. "Permission denied" running job. chmod +x or wrong path.
  2. Pending forever. Too many nodes/walltime.

Long Written

  1. salloc interactive vs sbatch batch (250 words).

    sbatch and salloc request the same resources through the same scheduler but serve opposite phases of work. sbatch run.sbatch submits a script: SLURM queues the job, and when nodes free up it runs the script unattended — output to --output files, environment rebuilt inside the script (module loads included), results collected via sacct afterwards. It is fire-and-forget: reproducible (the script is the record, versionable in Git), immune to your laptop sleeping, chainable via --dependency, and the only sane mode for 24-hour production runs or 100-task array sweeps. salloc --nodes=1 --time=1:00:00 instead reserves resources and returns a shell holding the allocation; commands you type run through srun on the allocated node(s), and srun --pty bash gives a live prompt on compute hardware. This is the debugging and experimentation mode: rebuild, run a 4-rank test under gdb, inspect a crashing case interactively, measure a kernel — with human latency in the loop but scheduler-managed fairness, unlike abusing the login node. The costs invert: interactive allocations waste core-hours whenever you think instead of compute, and they die with your connection (pair with tmux); batch jobs cost nothing while queued but debug slowly — each attempt is a queue round-trip. The professional workflow the exam wants: prototype under salloc/srun on a small case in the short/test partition, freeze the commands into an sbatch script, then submit the real run with sbatch and monitor via squeue. Same allocator, two doors: one for humans, one for jobs.

Mixed-Topic Integration Questions

  1. Edit→commit→push→build→submit→post-process pipeline. Combine Vim + Git + ssh + Makefile/CMake + sbatch + awk + gnuplot. Reference each chapter.
  2. Why does rsync -avz matter for git clone on a cluster? Not directly; but rsync for big result transfer + git for code.
  3. Predict residuals time series for a CFD case based on the script in Ch.7 §7. Apply pipeline mentally.
  4. Why does compile + sanitizer + valgrind matter together? Sanitizers fast pass, valgrind deep audit; the build step decides.
  5. How many cores total in a SBATCH nodes=4 ntasks-per-node=2 cpus-per-task=8? 64.

End of question bank.