Skip to content

Commit bd8a43e

Browse files
committed
Merge branch 'grigorik/development' of https://github.com/EngineeringSoftware/pkdb into grigorik/development
2 parents a404237 + 4c231c1 commit bd8a43e

17 files changed

Lines changed: 281 additions & 165 deletions

benchmarks/run_boltzmann_debuggers.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"""
88

99
import argparse
10+
import re
1011
import subprocess
1112
import sys
1213
import time
@@ -21,10 +22,21 @@
2122
system_and_suffix,
2223
write_checkpoint,
2324
)
24-
from run_boltzmann import parse_total_time_s
2525

2626
DEFAULT_SPACES = ["DebugOpenMP", "DebugCuda"]
2727

28+
29+
def parse_total_time_s(stdout: str) -> float | None:
30+
"""Last "total time = <float>" line (warmup + RESET produce an earlier one)."""
31+
matches = list(
32+
re.finditer(
33+
r"^total time = ([0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?)\s*$",
34+
stdout,
35+
re.MULTILINE,
36+
)
37+
)
38+
return float(matches[-1].group(1)) if matches else None
39+
2840
# Step counts passed to boltzmann/main.py via -s. Every run here pays Python-level tracing on top
2941
# of the kernels, so the wall clock is far higher than run_boltzmann.py's own timing.
3042
STEP_COUNTS = [

benchmarks/run_ewald_debuggers.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"""
88

99
import argparse
10+
import re
1011
import subprocess
1112
import sys
1213
import time
@@ -21,10 +22,61 @@
2122
system_and_suffix,
2223
write_checkpoint,
2324
)
24-
from run_ewald import parse_walltimes
2525

2626
DEFAULT_SPACES = ["DebugOpenMP", "DebugCuda"]
2727

28+
KERNEL_KEYS = ["P2P", "P2G", "FFT", "CNV", "IFFT", "G2P"]
29+
30+
31+
def parse_walltimes(stdout: str) -> dict[str, float | None] | None:
32+
"""Last "Ewald Walltimes" section: TOTAL plus each KERNEL_KEYS component's "tot" value."""
33+
lines = [re.sub(r"\x1b\[[0-9;]*m", "", line).strip() for line in stdout.splitlines()]
34+
35+
start = None
36+
for i in range(len(lines) - 1, -1, -1):
37+
if "Ewald Walltimes" in lines[i]:
38+
start = i
39+
break
40+
if start is None:
41+
return None
42+
43+
end = len(lines)
44+
for i in range(start + 1, len(lines)):
45+
if "Ewald Cost Model" in lines[i]:
46+
end = i
47+
break
48+
49+
result: dict[str, float | None] = {
50+
"TOTAL": None,
51+
**{key: None for key in KERNEL_KEYS},
52+
}
53+
component = None
54+
for line in lines[start + 1 : end]:
55+
header = re.match(r"^(P2P|P2G|FFT|CNV|IFFT|G2P)\s*:", line)
56+
if header:
57+
component = header.group(1)
58+
continue
59+
60+
m_total = re.match(r"^TOTAL:\s*([0-9eE+\-.]+)", line)
61+
if m_total:
62+
try:
63+
result["TOTAL"] = float(m_total.group(1))
64+
except ValueError:
65+
pass
66+
component = None
67+
continue
68+
69+
if component is not None:
70+
m_tot = re.search(r"['\"]?tot['\"]?\s*:\s*([0-9eE+\-.]+)", line)
71+
if m_tot:
72+
try:
73+
result[component] = float(m_tot.group(1))
74+
except ValueError:
75+
pass
76+
component = None
77+
78+
return result
79+
2880
# Atom counts passed to Ewald via --atoms. Every run here pays Python-level tracing on top of the
2981
# kernels, so the wall clock is far higher than run_ewald.py's own timing.
3082
ATOM_SIZES = [

benchmarks/run_examinimd_debuggers.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,32 @@
2121
system_and_suffix,
2222
write_checkpoint,
2323
)
24-
from run_examinimd import parse_total_seconds
2524

2625
DEFAULT_SPACES = ["DebugOpenMP", "DebugCuda"]
2726

27+
28+
def parse_total_seconds(stdout: str) -> float | None:
29+
"""Sum the Total(s) column of the kernel profile table ExaMiniMD prints."""
30+
total = 0.0
31+
found = False
32+
in_table = False
33+
for line in stdout.splitlines():
34+
stripped = line.strip()
35+
if not in_table:
36+
in_table = stripped.startswith("Kernel") and "Total(s)" in stripped and "Avg(ms)" in stripped
37+
continue
38+
if not stripped:
39+
break
40+
parts = stripped.split()
41+
# Data rows look like: <name> <Count> <Total(s)> <Avg(ms)> <Percent%>
42+
if len(parts) >= 5 and parts[-1].endswith("%") and parts[-4].isdigit():
43+
try:
44+
total += float(parts[-3])
45+
found = True
46+
except ValueError:
47+
pass
48+
return total if found else None
49+
2850
# Atom counts passed to ExaMiniMD via --atoms. Small next to run_examinimd.py's list: every
2951
# run here pays Python-level tracing on top of the kernels, so the wall clock is far higher.
3052
ATOM_SIZES = [

sbatch-scripts/TACC/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# TACC sbatch scripts and apptainer file
2+
3+
First, build container with apptainer:
4+
5+
```bash
6+
module load tacc-apptainer
7+
apptainer build pkdb_container.sif pkdb_container.def
8+
```
9+
10+
Do `pkdb` installation of `PyKokkos` and `pkdb`:
11+
12+
```bash
13+
apptainer shell --nv --fakeroot conda_git.sif
14+
Apptainer> cd [pkdb_dir]/pykokkos
15+
Apptainer> conda create -n pkdb python=3.13 -y
16+
Apptainer> conda env update -n pkdb -f base/environment.yml
17+
Apptainer> conda activate pkdb
18+
Apptainer> python install_base.py install --verbose -- -DENABLE_LAYOUTS=ON -DENABLE_MEMORY_TRAITS=OFF -DENABLE_VIEW_RANKS=4 -DENABLE_THREADS=OFF -DENABLE_OPENMP=ON -DENABLE_CUDA=ON
19+
Apptainer> conda install -c conda-forge pybind11 patchelf -y
20+
Apptainer> pip install -e .
21+
Apptainer> cd [pkdb_dir]/pkdb
22+
Apptainer> pip install -r requirements.txt
23+
Apptainer> pip install -e .
24+
```
25+
26+
Now, when our environment is ready we can run sbatch scripts. Execute scripts
27+
and pass apptainer directory (`./`, if you are doing it from current directory)
28+
and `pkdb` directory (`../../` if you are doing it from current directory). It's
29+
not required to pass absolute path.
30+
For example:
31+
32+
```bash
33+
sbatch tacc_examinimd.sh ./ ../../
34+
```

sbatch-scripts/TACC/pkdb_env.def

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Bootstrap: docker
2+
From: ubuntu:22.04
3+
4+
%environment
5+
export PATH="/opt/conda/bin:$PATH"
6+
7+
%post
8+
set -e
9+
10+
# Set apt downloads to root user env
11+
echo 'APT::Sandbox::User "root";' > /etc/apt/apt.conf.d/99no-sandbox
12+
apt-get update
13+
14+
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
15+
wget \
16+
bzip2 \
17+
ca-certificates \
18+
git \
19+
gdb \
20+
build-essential
21+
22+
# Install miniconda
23+
ARCH=$(uname -m)
24+
case "${ARCH}" in
25+
x86_64) MINICONDA_ARCH="x86_64" ;;
26+
aarch64|arm64) MINICONDA_ARCH="aarch64" ;;
27+
*) echo "Unsupported architecture: ${ARCH}" >&2; exit 1 ;;
28+
esac
29+
MINICONDA_INSTALLER=Miniconda3-latest-Linux-${MINICONDA_ARCH}.sh
30+
wget -q https://repo.anaconda.com/miniconda/${MINICONDA_INSTALLER} -O /tmp/${MINICONDA_INSTALLER}
31+
bash /tmp/${MINICONDA_INSTALLER} -b -p /opt/conda
32+
rm /tmp/${MINICONDA_INSTALLER}
33+
export PATH="/opt/conda/bin:$PATH"
34+
35+
# conda TOS and prerequisites
36+
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main
37+
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r
38+
conda install -y -c nvidia cuda-nvcc cuda-gdb
39+
conda clean -afy
40+
41+
# Pass existing tool references to container
42+
ln -sf /opt/conda/bin/nvcc /usr/local/bin/nvcc
43+
ln -sf /opt/conda/bin/conda /usr/local/bin/conda
44+
ln -sf /opt/conda/bin/cuda-gdb /usr/local/bin/cuda-gdb
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
#SBATCH -A <Your project>
4+
#SBATCH -J pkdb_boltzmann_evaluation
5+
#SBATCH -o boltzmann_job.out
6+
#SBATCH -p gh
7+
#SBATCH -N 1
8+
#SBATCH -n 1
9+
#SBATCH -t 06:00:00
10+
11+
# ------------------
12+
# Main code section
13+
# ------------------
14+
15+
if [ -z "$1" ] || [ -z "$2" ]; then
16+
printf "Script requires two paths: \n\t(1) apptainer .sif image path\n\t(2) pkdb root directory\n"
17+
exit 1
18+
fi
19+
20+
APPTAINER_PATH="$(realpath "$1")"
21+
PKDB_ROOT="$(realpath "$2")"
22+
23+
module load tacc-apptainer
24+
apptainer exec --nv --fakeroot "$APPTAINER_PATH" bash -c '
25+
set -e
26+
export CUDACXX=/opt/conda/bin/nvcc
27+
export CXX=/usr/bin/g++
28+
export CC=/usr/bin/gcc
29+
eval "$(conda shell.bash hook)"
30+
conda activate pkdb
31+
32+
export OMP_NUM_THREADS=72
33+
BENCH_ROOT="$(realpath "$1/benchmarks")"
34+
cd "$BENCH_ROOT"
35+
python run_boltzmann_debuggers.py --spaces "DebugCuda, DebugOpenMP"
36+
' _ "$PKDB_ROOT"
37+
38+
echo "Done."

sbatch-scripts/TACC/tacc_ewald.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
#SBATCH -A <Your project>
4+
#SBATCH -J pkdb_ewald_evaluation
5+
#SBATCH -o ewald_job.out
6+
#SBATCH -p gh
7+
#SBATCH -N 1
8+
#SBATCH -n 1
9+
#SBATCH -t 06:00:00
10+
11+
# ------------------
12+
# Main code section
13+
# ------------------
14+
15+
if [ -z "$1" ] || [ -z "$2" ]; then
16+
printf "Script requires two paths: \n\t(1) apptainer .sif image path\n\t(2) pkdb root directory\n"
17+
exit 1
18+
fi
19+
20+
APPTAINER_PATH="$(realpath "$1")"
21+
PKDB_ROOT="$(realpath "$2")"
22+
23+
module load tacc-apptainer
24+
apptainer exec --nv --fakeroot "$APPTAINER_PATH" bash -c '
25+
set -e
26+
export CUDACXX=/opt/conda/bin/nvcc
27+
export CXX=/usr/bin/g++
28+
export CC=/usr/bin/gcc
29+
eval "$(conda shell.bash hook)"
30+
conda activate pkdb
31+
32+
export OMP_NUM_THREADS=72
33+
BENCH_ROOT="$(realpath "$1/benchmarks")"
34+
cd "$BENCH_ROOT"
35+
python run_ewald_debuggers.py --spaces "DebugCuda, DebugOpenMP"
36+
' _ "$PKDB_ROOT"
37+
38+
echo "Done."

0 commit comments

Comments
 (0)