Hardware validation checklist¶
Everything in this repository is tested without hardware: with fake command runners, fake clocks, a fake sysfs tree and a local mode that simulates all nodes on one machine. The items below are the physical checks that only the real testbed can answer. Each item names the requirement it closes (IDs from the thesis requirement catalogue), the steps, and the expected outcome. Record the outcome and the date next to each item.
Software stack (A-07, J-19)¶
- [ ] On one Raspberry Pi 4 (Raspberry Pi OS Bookworm 64-bit, Python 3.11): create a virtual environment and install
requirements/edge_device.lockwithpip install --require-hashes -r requirements/edge_device.lock. Expected: every wheel is found foraarch64andcp311;python -c "import tensorflow; print(tensorflow.__version__)"prints2.15.1. - [ ] Same device: install
requirements/edge_device_llm.lock. Expected:torch2.1.2 andtransformers4.46.3 import;torch.get_num_threads()returns 4. - [ ] Note the wall-clock time of each installation (J-15; the thesis states about 25 minutes per device for the whole deployment).
Process control (C-02)¶
- [ ] On a device, run
python -m src.config --envthrough SSH and confirm the printedTESTBED_*values matchconfig.yaml. - [ ] Start a tagged process over SSH with the start command of
src/common/process_tags.py(for example asleep 60), close the SSH session, reconnect and run the check command. Expected:running. Run the stop command. Expected:stopped, no process with the tag inps, PID file removed.
Compute load (G-01, J-03)¶
- [ ] On a device, run
python -m src.testbed.load_generator --cpu 50 --duration 60and watchtopormpstat -P ALL 1. Expected: one core at about 50 % (within 5 points), the others idle. - [ ] Run
--regime heavy --duration 120 --log /tmp/load.json. Expected: total CPU use between 60 and 80 % of one core, memory in use between 50 and 60 % (free -m), both changing every 10 s;/tmp/load.jsonlists the drawn targets. - [ ] Run
--processes 2 --duration 30. Expected: two cores fully busy.
Network shaping (G-02, G-03, C-07)¶
- [ ] On a device,
scripts/end_device/apply_latency.sh wlan0 20 20 --once, thenping -c 10 <edge server>from the device. Expected: RTT about 20 ms above the baseline.apply_latency.sh wlan0 --clearrestores the baseline. - [ ]
python -m src.testbed.latency_injector wlan0 --delay 10 --jitter 5 --loss 1 --rate 10, theniperf3 -c <edge server> -t 10andping -c 50. Expected: about 10 Mbit/s, RTT 10 ms +- 5 ms, about 1 % loss. - [ ] Per destination:
--dst <edge server IP> --delay 15 --dst <another device IP> --delay 30. Expected: the two pings differ by about 15 ms. - [ ] Note any driver that rejects the HTB tree on
wlan0; the single-root fallback (apply_all) is the alternative.
Heterogeneity and frequency (G-04, B-04, F-01)¶
- [ ] Device:
sudo python -m src.testbed.heterogeneity freq --max-mhz 600 --state /tmp/f.json, thenpython -m src.testbed.resource_monitor --output /tmp/m.json --run-id t --node-id d --duration 10. Expected:frequencies_khzat or below 600000 in every sample;freq --restore /tmp/f.jsonbrings them back to 1800000. - [ ] Device:
sudo python -m src.testbed.heterogeneity cgroup create --name testbed-check --memory-mb 512, then runsh -c "$(python -c 'from src.testbed.heterogeneity import MemoryLimit; print(MemoryLimit().attach_command("testbed-check", "python3 -c \"x=bytearray(700*2**20)\""))')". Expected: the allocation is killed by the OOM killer of the group;cgroup removecleans up. - [ ] Edge server:
sudo python -m src.testbed.cpu_frequency apply --state /tmp/s.json, thenverify. Expected: governorperformance, turbo disabled, every core near the base frequency;restorereturns the previous settings. - [ ] Device under a long heavy load: the monitor trace shows the temperature and whether
throttledever leaves0x0; the monitor's own CPU use (top -p <pid>) stays below 2 %.
Power and throughput (F-04, F-08, J-07)¶
- [ ] Device with INA260:
pip install -r requirements/power.in, thenpython -m src.network.power_measurement --interval 0.2 --duration 30 --output /tmp/p.json --run-id t --node-id d. Expected: about 150 samples, idle power 2.5-3.5 W,energy_jconsistent with power x 30 s. - [ ] Device:
python -m src.network.throughput_measurement --server <edge server> --duration 10 --output /tmp/tp.jsonwithiperf3 -s -1on the edge server, once alone and once with all five devices at the same time. Record the figures (the thesis states 80-120 Mbit/s per device and, in Chapter 5, a measured 19.6 Mbit/s).
Partitioned inference and per-phase timing (B-05, D-05)¶
- [ ] Edge server (data-plane address):
python -m src.inference.server --model alexnet --weights models/alexnet.npz --policy SJF --port 5300 --nodes device1,device2,device3,device4. Device:python -m src.inference.client --model alexnet --weights <ed_root>/models/alexnet.npz --server <edge server>:5300 --s 0 --s 4 --s 8 --s 11 --repetitions 10 --output /tmp/phases.json --run-id t --node-id device1. Expected:transmission_msgrows with the transmitted size (s = 1 is the largest cut, s = 8 is 36 KB),remote_msshrinks with s, s = 11 has no transmission. - [ ] Four devices at once with
--s 4and--policy SJF, then--policy RR: the per-devicequeue_msvalues follow the policy (SJF: ascending offloaded work; RR: interleaved), as in the loopback tests. - [ ] Compare the measured
transmission_msof the s = 1 cut (1.1 MB) with size / throughput from the iperf3 figure plus the ping RTT.
Whole pipeline on the testbed (C-01, C-04, C-13, D-10, D-13)¶
- [ ] Edge server:
scripts/base_station/run_full_benchmarking.sh examples/scenarios/baseline.yaml. Expected: every device runstrain_and_run_benchmark.sh both, the three output files appear inresults/<run id>/,nodes.jsongains statistics, andjournal.jsonshows every entry undone. - [ ] Edge server:
scripts/base_station/run_experiment.sh examples/scenarios/heavy_load.yaml. During the run, on a device:tc qdisc show dev wlan0lists the netem (and tbf) queue,topshows the load generator and the monitor; after the run both are gone andtc qdisc showis back to the default. The monitor trace inresults/<run id>/monitor/shows the heavy regime's CPU and memory levels. - [ ] Start skew (C-04): in
results/<run id>/raw/, compare theorigin.wall_time_sof the devices' records. Expected: within the NTP offset (sub-millisecond on the wired management network). - [ ] Interrupt a run with Ctrl-C during profiling, then run
scripts/base_station/clean_devices.sh. Expected: notestbed-process, no netem queue and notestbed-cgroup remains on any device. - [ ] NTP guard: stop chrony on one device and start a run. Expected: the preflight refuses the run with the offending node named.
LLM profiling and HeadSplit (A-02, D-04, I-03, I-04)¶
- [ ] Device with the LLM environment and a TinyLlama checkpoint in the mirror:
python -m src.models.torch.hooks --model tinyllama --weights <checkpoint dir> --seq-len 256 --repetitions 3 --output /tmp/blocks.json. Expected: per layer, FFN time about nine times the projection and the attention heads a few milliseconds each (Chapter 5, Table small-real-blocks gives 2.4-6.7 ms per head, 27-64 ms projection, 0.23-0.62 s FFN at 1.8 GHz and four threads);TESTBED_THREADS=1roughly doubles them. - [ ] Device:
scripts/end_device/train_and_run_benchmark.sh both <models dir> gpt2 /tmp/r --repetitions 2withTESTBED_MODEL_WEIGHTSpointing at a GPT-2 checkpoint directory (or random weights): per-layer stage times and the logits stage are recorded;python -m src.inference.client --model gpt2 ...against the edge-server service moves the hidden-state cut (T x 768 floats) over the wireless link. - [ ] HeadSplit: provision the devices with
headsplit_commitset; on the controller device runscripts/profile_offline.pyonce (needs the calibration data) to produceartifacts/profile.json; thenscripts/base_station/run_experiment.sh examples/scenarios/ch6_rtt_sweep.yaml. Expected: one run per added RTT value,results/<run id>/headsplit/results.jsonwith the layer_based, head_only and headsplit totals, and the monitor and power traces of every worker. Compare the slopes with Chapter 6 (0.15 s and 1.1 s per millisecond of added RTT).
NNPM web application (C-05 to C-10, J-14)¶
- [ ] Edge server:
nnpm(orpython -m gui.app), then openhttp://<management address>:<nnpm_port>/from a laptop on the management network. Expected: the page title reads "Neural Network Architecture Partitioning (NNPM) manager", every node ofnodes.jsonhas a marker, the edge server included, and the map tiles load from the configured source (or the grid appears withmap_offline: true). - [ ] Power off one device. Expected: its marker turns red within two probe rounds (about 4 s) while the others stay green; power it on again and it turns green once three of three pings succeed.
- [ ] Enable "Add node by clicking the map", click a position, type an id and the device's addresses, save. Expected:
nodes.jsoncontains the clicked coordinates; the marker appears at the clicked position; dragging it updates the coordinates in the file. - [ ] Click a device marker after a benchmarking run. Expected: the panel shows the last-measured latency, available memory and CPU usage with the time of the measurement.
- [ ] Create Scenario, "Derive latencies from the map", "Save and run". During the run, on the device:
tc qdisc show dev <interface>showsnetem delay <derived value>ms; the panel's ping value is close to the injected one. After the run the queue is gone. - [ ] Benchmarking dialog with the default values. Expected: the terminal shows the
[node][stream]lines of every device as they are produced; the three output files appear underresults/<run id>/. - [ ] Optimise dialog on that run: greedy, SJF,
50%. Expected: the table and the JSON file underresults/<run id>/optimisation/. - [ ] Press Stop during a run. Expected: the run is reported as aborted, and on every device no
testbed-process, no netem queue and notestbed-cgroup remains.
Provisioning, access point, time synchronisation (H-01, H-02, B-06, F-06, A-08, J-15)¶
- [ ] Edge server (Ubuntu 22.04, USB 802.11ac adapter as
ap_interface):scripts/provision/provision_edge_server.sh --allow-upstream, thenscripts/provision/build_mirror.sh wheelsandbuild_mirror.sh headsplit(withheadsplit_commitset). Expected:hostapd,dnsmasq,chrony,testbed-mirrorandnnpmare active; a laptop sees the SSID and, when joined, gets an address from the data-plane pool and no default route;curl http://<management address>:<mirror_port>/wheels/aarch64/lists the wheels. Record the elapsed time fromresults/provisioning/timing.log. - [ ] Flash the 64-bit Raspberry Pi OS Bookworm image, mount its boot partition and run
scripts/provision/prepare_image.sh device1 /media/.../bootfs. Boot the device on the management switch. Expected: within a minutejournalctl -u dnsmasqon the edge server shows a lease fordevice1at itsnodes.jsonmanagement address, andssh pi@device1works with the edge server's key only. - [ ]
scripts/provision/build_mirror.sh apt device1once (the reference device downloads the Debian packages), thenbuild_mirror.sh manifest. Expected:mirror/apt/Packages.gzexists;python -m src.provisioning.mirror verifyprints "mirror matches its manifest". - [ ]
scripts/provision/provision_device.sh device1 --llmwith the edge server's internet access disabled. Expected: the device ends with both static addresses,apt-get updateon it contacts only the mirror,pipshowsno-index,sudo -n tc qdisc showworks for the device user andsudo -n lsdoes not;chronyc trackingshows the edge server as the reference. Record the elapsed time (the thesis quotes about 25 minutes per device; the measured figure replaces the "from source" wording, J-15). Run the script a second time: expected "unchanged" for every file and no reinstallation. - [ ] Flash a 32-bit image on a spare card and run
prepare_image.sh. Expected: refused with "32-bit image". Boot a device from a 32-bit card and runprovision_device.sh. Expected: refused with the kernel architecture named. - [ ] Repeat the device steps for the remaining four devices; record the total time from the blank cards to the five provisioned devices (the thesis quotes two hours for the whole testbed).
- [ ] NTP offset (F-06): after ten minutes, on every device
chronyc trackingandchronyc sources -v. Expected: the only source is the edge server and the system-time offset is below 1 ms (sub-millisecond, Chapter 3); record the values. Start a run: the preflight accepts all devices withntp_offset_threshold_ms: 1.0. - [ ] Access point (B-06):
iw dev <ap_interface> infoon the edge server shows the configured channel at 80 MHz;iw dev wlan0 linkon a device shows the 5 GHz frequency and a VHT rate. Measure the single-device throughput withsrc.network.throughput_measurement(F-08 item above).
(Items are added with every work package.)
Extensions of version 1.1 (HeadSplit through NNPM, generic adapters, catalogue)¶
- [ ] Runtimes dialog, HeadSplit, Check the devices before provisioning HeadSplit: every device red on checkout and environment. After Install or update HeadSplit on all devices: checkout green with the pinned commit, environment green with the
torchandtransformersversions. - [ ] Build the speculation profile with
allow_upstreamon the edge server (internet reachable): the task completes,artifacts/profile.jsonappears on the controller and its check turns green; note the duration. - [ ]
python -m src.models.weights fetch tinyllama --allow-upstream, then Distribute a checkpoint: the checksums verify on every device and the checkpoint check turns green. - [ ] A HeadSplit scenario created in the dialog (controller, four workers, mode
all, 50 tokens) runs to completion; the summary page shows the three modes with totals of the order reported in Chapter 6, and the sweep table for anadded_rtt_mssweep created in the dialog. - [ ]
model: mobilenetv2andmodel: efficientnetb0on one device (train_and_run_benchmark.sh bothwith--model-args '{"input_size": 224}'): the stages build on the Pi within its memory, the benchmark completes, andpython -m src.models.inference verifyreportsokfor every partition point. - [ ]
model: hf_decoderwithmodel_args: {checkpoint: <models dir>/Qwen__Qwen2.5-0.5B, seq_len: 32}on one device: the stages run; note the per-layer times. - [ ] A scenario with
input: {source: image_folder, path: <folder with class sub-directories>}andchecks: {partition_equivalence: true}on the devices: the verification files are collected and report top-1 accuracy.