Bring a fresh machine to a state where PACT can run. Do this before
building ../src/ or using ../run/.
| Subdir | Purpose |
|---|---|
kernel/ |
Build, install, and boot vanilla Linux 6.3, then build and load the two modules the tiering subsystem requires - tierinit (registers the slow tier + demotion targets) and kswapdrst (keeps kswapd/demotion from stalling). |
env/ |
Prepare the machine for controlled runs: uncore-frequency pinning, CXL/NUMA layout, performance governor, and disabling turbo / THP / KSM / NUMA-balancing. |
- Kernel -
kernel/:setup_kernel.sh→ reboot into 6.3. - Fast-tier size - shrink node 0 with a
memmap=boot parameter → reboot again (see Set the local fast-tier DRAM size below). This is what creates the fast/slow capacity split; without it the whole workload fits in local DRAM and PACT has nothing to migrate. - Modules -
kernel/:build_modules.sh, then loadtierinit.ko+kswapdrst.ko(or letrun-pact.shload them). - Environment -
env/:sudo ./prepare_environment.sh(or let the runner do it viarun_setup_config=true ./run-pact.sh ...).
Re-run
prepare_environment.shafter EVERY reboot. Its effects (node-1 CPUs offline, uncore frequency, THP/KSM/NUMA-balancing off) are runtime-only and do NOT persist across a reboot. In particular, after thememmapreboot in step 2 you must run it again before measuring, or the slow tier still has online CPUs and the run is invalid. The modules (step 3) also need reloading after a reboot;run-pact.shreloads them automatically.
The env scripts source each other by their own location, so they can be
invoked from anywhere (e.g. the runner calls
../setup/env/prepare_environment.sh).
The slow tier is emulated by a remote NUMA node with its CPUs taken offline
and its uncore frequency pinned low. check_cxl_conf now aborts if Node 1
still has online CPUs (an unvalidated layout silently produces invalid
results). Two things are not auto-validated and you should confirm them:
-
Topology - after
prepare_environment.sh, the slow-tier node must be CPU-less:numactl --hardware # 'node 1 cpus:' should be empty -
Latency - the emulated tiers should land near the paper's targets (~90 ns local DRAM, ~140 ns remote NUMA, ~190 ns CXL-emulated; see
../modeling/README.md). Measure with a pointer-chase latency tool (e.g. Intel MLC--latency_matrix, or theptr_chasemicrobenchmark) and adjust the uncore-frequency targets inenv/modify-uncore-freq.sh/UNCORE_ARGSuntil the slow tier matches. Pinning the frequency without checking the resulting latency is the most common source of invalid tiering results.
The fast/slow split is created by making the fast tier (node 0) physically
small with a memmap= boot parameter, so first-touch fills node 0 and the
overflow spills to the slow tier. Do NOT use a cgroup memory limit for this: a
memcg cap limits total usage (not fast-tier residency) and deadlocks the
workload in D-state when demotion is disabled.
For a target fast:slow ratio R:1, set node-0 usable DRAM to
RSS x R/(R+1):
| Ratio (fast:slow) | node-0 usable DRAM |
|---|---|
| 1:1 (paper default) | RSS / 2 |
| 1:2 | RSS / 3 |
| 8:1 | RSS x 8/9 |
Measure the workload's RSS first, on an unconstrained boot:
/usr/bin/time -v numactl -C 2-9 --membind 0 \
env OMP_NUM_THREADS=8 ./bc -f kron.sg -i1 -n1 # "Maximum resident set size"memmap=<R>G!<off>G reserves <R> GB of DRAM starting at <off> GB, removing
it from node 0. Add it to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub,
then sudo update-grub and reboot.
# c220g5: node 0 is ~95 GB. To leave ~10 GB usable (a 1:1 split for a ~19.5 GB
# RSS bc-kron), reserve ~86 GB:
sudo sed -i 's/\(GRUB_CMDLINE_LINUX_DEFAULT="[^"]*\)"/\1 memmap=86G!2G"/' /etc/default/grub
sudo update-grub && sudo reboot
# After reboot, confirm node 0 free ~= RSS/2:
numactl -H | grep -E 'node 0 (size|free)' # e.g. size 10676 MB, free ~10 GBThe exact node-0 size for a given
memmapvaries by ~hundreds of MB each boot and by machine - tune the reserved GB up/down by 1-2 and re-checknumactl -Huntilnode 0 freeis close to your target. On a fresh boot the OS holds only ~0.5 GB of node 0, sonode 0 free ~= node 0 size. Verified values (c220g5, bc-kron 8t, RSS ~19.5 GB):memmap=86G!2Ggives node 0 ~10.7 GB total / ~10 GB free = 1:1.memmap=76G!2Ggives ~20 GB = the FULL RSS (no split - do not use for a 1:1 experiment).
- The current scripts assume a 2-NUMA-node server (one fast tier, one CXL-like slow tier).