Purpose
stress_gen.sh generates a simulated load (via stress-ng) for evaluation
purposes. Use it when you want a controlled, repeatable synthetic load — or
substitute the actual workload you want to evaluate. Either drives the
platform so a power profile/cap and the power monitor can be assessed; this
skill only automates the simulated path.
Terminology
Acronyms and terms used throughout this skill.
| Term |
Meaning |
| stress-ng |
The load-generation tool this skill drives to exercise the CPU and integrated GPU. |
| CPU worker |
One stress-ng process pinned to CPU work; cpus sets how many run in parallel. |
| load (per-CPU %) |
How hard each CPU worker pushes, 1..100 (100 = flat out). |
| GPU worker |
A stress-ng process targeting the single iGPU; gpu is a worker count, not a number of GPUs. |
| iGPU |
The integrated GPU inside the CPU package (exposed as an Intel render node). |
| render node |
/dev/dri/renderD* — the device GPU workers use; absent = software-rendering fallback. |
| nproc |
The number of logical CPUs; the default and upper bound for cpus. |
| PkgTmp / PkgWatt |
Package temperature / power (from turbostat) sampled before and during load for the report. |
| PL1 / PL2 |
Sustained / short-burst power limits; a bounded stress run reveals sustained (PL1) vs burst (PL2) behavior. |
| duration |
How long to run (stress-ng time syntax, e.g. 60s, 5m); omit to run until stopped. |
| dry_run |
Preview mode: show the resolved command without launching anything. |
Trigger Phrases
- generate platform stress
- stress the cpu / stress the gpu
- create cpu load / create gpu load
- run a stress test
- load the platform for power measurement
- stress-ng cpu gpu
- burn-in the cpu
- stress N cpus at P percent
- exercise the power profile under load
Required Inputs
- enib_home: absolute path to this repository root (default: current workspace root). On a host provisioned with Infrastructure Blueprint, the developer source tree lives at
/opt/edge/developer, so enib_home is /opt/edge/developer on the target system.
- cpus: number of CPU workers,
1..nproc (default: all CPUs / nproc)
- load: per-CPU load percentage,
1..100 (default: 100)
- gpu: number of stress-ng GPU worker processes targeting the single iGPU,
0..12 (default: 4; 0 disables GPU stress). This is a worker count, NOT a GPU count. Use a maximum of 4 workers for a 4 Xe-core iGPU and 12 workers for a 12 Xe-core iGPU.
- duration: optional stress-ng timeout, e.g.
60s, 5m, 2h (default: run until stopped / Ctrl-C)
- dry_run:
true | false (default: false). When true, only the resolved command is shown; nothing is launched.
- auto_confirm:
true | false (default: false). When true, skip the confirmation gate.
Preconditions
Run silently without user prompts:
Prompt only for missing required inputs:
Input validation (fail closed before launch):
Steps
Terminal command rules (MUST follow for every command in this skill):
- Always invoke scripts by absolute path — never prefix with
cd.
- Never combine
cd with any output redirection in the same compound command — VS Code blocks it with an approval dialog.
- Never use
$(...) command substitution in terminal commands — VS Code blocks them with an approval dialog. The scripts handle all internal computation themselves.
Resolve the effective parameters and build the command (no launch yet):
- Base:
<enib_home>/tools/power-tuning/stress_gen.sh --cpus <cpus> --load <load> --gpu <gpu>
- Append
--duration <duration> only when supplied.
- Note: no
sudo is required; stress-ng runs as the current user.
Capture a brief pre-stress snapshot for the report (read-only, best-effort; skip entirely when dry_run=true):
- load average:
cat /proc/loadavg
- package temp/power if turbostat is available (single sample):
turbostat --quiet --interval 1 --num_iterations 1 --show PkgTmp,PkgWatt 2>/dev/null || true
Always render a Planned Load table from the resolved parameters before any launch — show it unconditionally, including when auto_confirm=true:
| Parameter |
Value |
| Command |
<resolved stress_gen.sh command> |
| CPU workers |
<cpus> of <nproc> |
| Load per CPU |
<load>% |
| GPU workers |
<gpu> (0 = off) |
| Duration |
<duration or 'until stopped'> |
| GPU render node |
<path or 'not found (software fallback)'> |
Confirmation gate — pause before launching:
- If
dry_run=true: stop here and record CONFIRMATION=dry_run_only. Do not launch.
- Else if
auto_confirm=true: log AUTO_CONFIRM=true and continue.
- Else: present the tabulated Planned Load and ask "Launch stress ( CPUs @ %, GPU workers, duration=<duration or 'until stopped'>)? (yes/no)". On anything other than
yes/y (case-insensitive), stop and record CONFIRMATION=declined.
Launch (only after confirmation):
- If
duration is set: run synchronously and let it complete; capture exit code.
- If
duration is NOT set (runs until stopped): run in the background so the run does not block; record the PID(s) via pgrep -x stress-ng and tell the user how to stop it (sudo pkill -x stress-ng, or Ctrl-C if launched in their own foreground terminal).
Confirm the stressor is active shortly after launch:
pgrep -x stress-ng returns at least one PID (for bounded runs, this is checked before completion).
Verify GPU load is real (only when gpu > 0) — a running GPU worker does
not by itself prove the iGPU is busy; it may be falling back to software
rendering. Confirm with as many of these as are available (best-effort,
read-only):
- iGPU engine utilization (most direct):
sudo intel_gpu_top -o - -s 1000 for a
couple of samples, or interactive sudo intel_gpu_top. The Render/3D
(and Blitter/Video) engine busy % should climb well above idle (toward
~100%). Requires intel-gpu-tools (sudo apt-get install -y intel-gpu-tools).
- Graphics power rises: sample
GFXWatt via turbostat
(turbostat --quiet --interval 1 --num_iterations 1 --show PkgTmp,PkgWatt,GFXWatt 2>/dev/null || true)
or the monitor-power-thermal skill — GFXWatt should rise above its idle
value under GPU load and fall when the run stops.
- Workers hold the render node:
sudo fuser -v /dev/dri/renderD128 should
list stress-ng-gpu PIDs attached to the device (proves attachment, not
work — pair with one of the signals above).
- If none of these move while GPU workers are "running", the load is not
reaching the iGPU (software fallback); note it and treat the run as CPU-only.
Capture a post/steady-state snapshot using the same reads as Step 2 (for bounded runs after completion; for open-ended runs, one sample a few seconds in).
Validation
Validation section is criteria-only. Do not render the pass/fail results table here.
- Preconditions passed (script executable;
stress-ng present; no pre-existing stress-ng instance).
cpus, load, gpu, and duration validated against their ranges/syntax.
- A Planned Load table was rendered unconditionally before the confirmation gate.
- Confirmation gate outcome recorded as one of:
confirmed, auto_confirm, declined, dry_run_only.
- Launch only occurred when the outcome is
confirmed or auto_confirm.
- After launch,
pgrep -x stress-ng shows the expected activity (one or more workers).
- For bounded runs (
duration set), the script exited with code 0 at completion.
- For open-ended runs, the PID(s) and stop instructions were reported to the user.
Rollback
- Stop an open-ended run at any time:
sudo pkill -x stress-ng (or Ctrl-C in the launching terminal).
- Stress load is transient and leaves no persistent state; stopping the process fully restores idle behaviour.
- If a power profile was applied via
set-power-profile before stressing, the profile persists (runtime-only) until reboot regardless of the stress run.
Safety Rules
- Do not launch if another stress-ng instance is already running (respect the script's own guard) — stacking stressors skews load and any power measurements.
- Warn before an open-ended (no
duration) high-load run on thermally constrained or fanless enclosures; recommend a bounded duration and monitoring temperature (see pt_mon.sh).
- Do not run with
sudo (stress-ng needs no root here); only use sudo for the documented pkill stop command.
- Do not launch GPU workers (
gpu > 0) as a way to interfere with a live display/compositor workload without the user's awareness.
- Never mask a failing precondition (missing stress-ng, existing instance) as success.
Expected Result Summary
Render the report as the following tables.
Run Metadata
| Field |
Value |
| Preconditions |
PASS/FAIL |
| Host |
<uname -m> + CPU model name |
| CPU workers |
<cpus> of <NCPU_MAX> |
| Per-CPU load |
<load>% |
| GPU workers |
<gpu> (0 = off) |
| Duration |
<duration or 'until stopped'> |
| Dry run only |
true / false |
| Confirmation |
confirmed / auto_confirm / declined / dry_run_only |
Launch Result
(omit when the outcome is declined or dry_run_only)
| Field |
Value |
| Command |
stress_gen.sh --cpus <n> --load <p> --gpu <g> [--duration <d>] |
| Mode |
synchronous (bounded) / background (open-ended) |
| stress-ng PID(s) |
<pids or n/a> |
| Exit code |
<code or 'running'> |
| Stop command |
sudo pkill -x stress-ng |
Load Snapshot (pre → during/post)
| Metric |
Before |
During/After |
| loadavg (1m) |
<value> |
<value> |
| PkgTmp (°C) |
<value or n/a> |
<value or n/a> |
| PkgWatt (W) |
<value or n/a> |
<value or n/a> |
| GFXWatt (W) |
<value or n/a> |
<value or n/a> |
GPU Load Verification
(only when gpu > 0; omit when the outcome is declined or dry_run_only)
| Signal |
Idle / Before |
Under Load |
Verdict |
iGPU engine busy % (intel_gpu_top) |
<value or n/a> |
<value or n/a> |
loaded / software-fallback / n/a |
| GFXWatt (turbostat) |
<value or n/a> |
<value or n/a> |
rose / flat / n/a |
Render node holders (fuser) |
— |
<stress-ng-gpu PID count or n/a> |
attached / none |
Validation Results
| Check Area |
Status |
Evidence |
Notes |
| script executable |
PASS/FAIL |
test -x result |
|
| stress-ng present |
PASS/FAIL |
command -v stress-ng |
install hint on FAIL |
| no pre-existing instance |
PASS/FAIL |
pgrep -x stress-ng |
list PIDs on FAIL |
| input range/syntax |
PASS/FAIL |
cpus/load/gpu/duration checks |
|
| stressor active |
PASS/FAIL/N/A |
pgrep -x stress-ng after launch |
N/A when not launched |
| iGPU actually loaded |
PASS/FAIL/N/A |
engine busy % / GFXWatt rise / render-node holders |
N/A when gpu = 0; FAIL = software fallback |
| bounded run completed |
PASS/FAIL/N/A |
exit code |
N/A for open-ended |
Failures and Troubleshooting
| Failed Check |
Raw Evidence |
Troubleshooting Note |
<check area> |
<snippet> |
<action> |
Troubleshooting Notes
stress-ng: command not found: install it with sudo apt-get install -y stress-ng (Debian/Ubuntu) and re-trigger.
- "stress-ng is already running": another instance is active. Stop it with
sudo pkill -x stress-ng (confirm with the user first), then re-trigger.
- Verify the iGPU is actually loaded (a running GPU worker is not proof — it
can fall back to software rendering). In order of directness:
sudo intel_gpu_top (from intel-gpu-tools) — the Render/3D engine busy
% should climb toward ~100% under load. Near-0% while workers run = fallback.
GFXWatt in pt_mon.sh / turbostat should rise above idle and drop when
the run stops.
sudo fuser -v /dev/dri/renderD128 should list stress-ng-gpu PIDs holding
the render node (confirms attachment; pair with one of the signals above to
confirm real work).
- GPU workers show little effect: confirm an Intel render node exists (
ls /dev/dri/renderD*) and that the build of stress-ng includes the gpu stressor (stress-ng --gpu 1 --timeout 2s should succeed); otherwise use --gpu 0 and stress CPU only.
- To watch the effect under load, run tools/power-tuning/pt_mon.sh in another terminal (PkgTmp/PkgWatt), remembering that
SysWatt may read 0.00 on platforms with a frozen psys counter.
- To combine with a power cap, apply a profile first via the
set-power-profile skill, then run this skill with a bounded duration to observe sustained (PL1) vs burst (PL2) behaviour.
- An open-ended run keeps the CPUs busy indefinitely; always provide a
duration for automated/unattended use so it self-terminates.
Related Skills
- monitor-power-thermal — run in another terminal to record PkgTmp/PkgWatt/GFXWatt while this load runs; the two are designed to be paired.
- set-power-profile — apply a package/platform power cap or named profile first, then stress to see how the limit holds under load.
- Typical loop: apply a limit/profile → start
monitor-power-thermal → run this skill with a bounded duration → read the min/mean/max summary.
1---2name: generate-platform-stress3description: Create controlled CPU and integrated-GPU load on an Intel host to see how the platform behaves when it is busy. Choose how many CPU workers to run, how hard each one pushes (per-CPU load %), how many GPU workers to run, and how long the load lasts — then start it with a single command via tools/power-tuning/stress_gen.sh (stress-ng). Ideal for validating a power profile or power cap under real load, checking thermal and power headroom, and running repeatable burn-in or benchmarking workloads.4---56## Purpose7`stress_gen.sh` generates a **simulated** load (via stress-ng) for evaluation8purposes. Use it when you want a controlled, repeatable synthetic load — or9substitute the **actual workload** you want to evaluate. Either drives the10platform so a power profile/cap and the power monitor can be assessed; this11skill only automates the simulated path.1213## Terminology14Acronyms and terms used throughout this skill.1516| Term | Meaning |17|---|---|18| stress-ng | The load-generation tool this skill drives to exercise the CPU and integrated GPU. |19| CPU worker | One stress-ng process pinned to CPU work; `cpus` sets how many run in parallel. |20| load (per-CPU %) | How hard each CPU worker pushes, `1..100` (100 = flat out). |21| GPU worker | A stress-ng process targeting the single iGPU; `gpu` is a **worker count**, not a number of GPUs. |22| iGPU | The integrated GPU inside the CPU package (exposed as an Intel render node). |23| render node | `/dev/dri/renderD*` — the device GPU workers use; absent = software-rendering fallback. |24| nproc | The number of logical CPUs; the default and upper bound for `cpus`. |25| PkgTmp / PkgWatt | Package temperature / power (from turbostat) sampled before and during load for the report. |26| PL1 / PL2 | Sustained / short-burst power limits; a bounded stress run reveals sustained (PL1) vs burst (PL2) behavior. |27| duration | How long to run (stress-ng time syntax, e.g. `60s`, `5m`); omit to run until stopped. |28| dry_run | Preview mode: show the resolved command without launching anything. |2930## Trigger Phrases31- generate platform stress32- stress the cpu / stress the gpu33- create cpu load / create gpu load34- run a stress test35- load the platform for power measurement36- stress-ng cpu gpu37- burn-in the cpu38- stress N cpus at P percent39- exercise the power profile under load4041## Required Inputs42- enib_home: absolute path to this repository root (default: current workspace root). On a host provisioned with Infrastructure Blueprint, the developer source tree lives at `/opt/edge/developer`, so `enib_home` is `/opt/edge/developer` on the target system.43- cpus: number of CPU workers, `1..nproc` (default: all CPUs / `nproc`)44- load: per-CPU load percentage, `1..100` (default: `100`)45- gpu: number of stress-ng GPU worker processes targeting the single iGPU, `0..12` (default: `4`; `0` disables GPU stress). This is a worker count, NOT a GPU count. Use a maximum of `4` workers for a 4 Xe-core iGPU and `12` workers for a 12 Xe-core iGPU.46- duration: optional stress-ng timeout, e.g. `60s`, `5m`, `2h` (default: run until stopped / Ctrl-C)47- dry_run: `true` | `false` (default: `false`). When `true`, only the resolved command is shown; nothing is launched.48- auto_confirm: `true` | `false` (default: `false`). When `true`, skip the confirmation gate.4950## Preconditions51Run silently without user prompts:52- [ ] Skill file exists and is readable:53 - `test -f <enib_home>/skills/generate-platform-stress/SKILL.md`54- [ ] The stress script exists and is executable:55 - `test -x <enib_home>/tools/power-tuning/stress_gen.sh`56- [ ] `stress-ng` is installed:57 - `command -v stress-ng`58 - if missing, stop and instruct: `sudo apt-get install -y stress-ng` (Debian/Ubuntu), then re-trigger.59- [ ] No stress-ng instance is already running (the script refuses to stack stressors):60 - `pgrep -x stress-ng`61 - if a PID is found, stop and report it; instruct the user to stop it first (`sudo pkill -x stress-ng`) before re-triggering.62- [ ] Determine the CPU worker ceiling:63 - `nproc` → `NCPU_MAX` (used to validate/derive `cpus`).64- [ ] Host is x86_64 with an Intel CPU (sanity check; non-fatal warning if not):65 - `uname -m` and `grep -m1 -o 'GenuineIntel' /proc/cpuinfo`66- [ ] (GPU only, non-fatal) an Intel render node exists when `gpu > 0`:67 - `ls /dev/dri/renderD* 2>/dev/null` — if absent, warn that GPU workers may fall back to software rendering.6869Prompt only for missing required inputs:70- [ ] Do not prompt for any value; all inputs have safe defaults (all CPUs at 100% + 12 GPU workers, run until stopped). Only ask if the user's request is ambiguous about whether GPU stress is wanted.7172Input validation (fail closed before launch):73- [ ] `cpus` is an integer in `[1, NCPU_MAX]`.74- [ ] `load` is an integer in `[1, 100]`.75- [ ] `gpu` is an integer in `[0, 12]`.76- [ ] `duration` (if supplied) matches stress-ng time syntax: `^[0-9]+(s|m|h|d)?$`.7778## Steps79**Terminal command rules (MUST follow for every command in this skill):**80- Always invoke scripts by **absolute path** — never prefix with `cd`.81- Never combine `cd` with any output redirection in the same compound command — VS Code blocks it with an approval dialog.82- Never use `$(...)` command substitution in terminal commands — VS Code blocks them with an approval dialog. The scripts handle all internal computation themselves.83841. Resolve the effective parameters and build the command (no launch yet):85 - Base: `<enib_home>/tools/power-tuning/stress_gen.sh --cpus <cpus> --load <load> --gpu <gpu>`86 - Append `--duration <duration>` only when supplied.87 - Note: no `sudo` is required; stress-ng runs as the current user.882. Capture a brief pre-stress snapshot for the report (read-only, best-effort; **skip entirely when `dry_run=true`**):89 - load average: `cat /proc/loadavg`90 - package temp/power if turbostat is available (single sample): `turbostat --quiet --interval 1 --num_iterations 1 --show PkgTmp,PkgWatt 2>/dev/null || true`913. **Always render a Planned Load table** from the resolved parameters before any launch — show it unconditionally, including when `auto_confirm=true`:9293 | Parameter | Value |94 |---|---|95 | Command | `<resolved stress_gen.sh command>` |96 | CPU workers | `<cpus>` of `<nproc>` |97 | Load per CPU | `<load>%` |98 | GPU workers | `<gpu>` (0 = off) |99 | Duration | `<duration or 'until stopped'>` |100 | GPU render node | `<path or 'not found (software fallback)'>` |1011024. **Confirmation gate** — pause before launching:103 - If `dry_run=true`: stop here and record `CONFIRMATION=dry_run_only`. Do not launch.104 - Else if `auto_confirm=true`: log `AUTO_CONFIRM=true` and continue.105 - Else: present the tabulated Planned Load and ask "Launch stress (<cpus> CPUs @ <load>%, <gpu> GPU workers, duration=<duration or 'until stopped'>)? (yes/no)". On anything other than `yes`/`y` (case-insensitive), stop and record `CONFIRMATION=declined`.1065. Launch (only after confirmation):107 - If `duration` is set: run **synchronously** and let it complete; capture exit code.108 - If `duration` is NOT set (runs until stopped): run in the **background** so the run does not block; record the PID(s) via `pgrep -x stress-ng` and tell the user how to stop it (`sudo pkill -x stress-ng`, or Ctrl-C if launched in their own foreground terminal).1096. Confirm the stressor is active shortly after launch:110 - `pgrep -x stress-ng` returns at least one PID (for bounded runs, this is checked before completion).1117. **Verify GPU load is real (only when `gpu > 0`)** — a running GPU worker does112 not by itself prove the iGPU is busy; it may be falling back to software113 rendering. Confirm with as many of these as are available (best-effort,114 read-only):115 - **iGPU engine utilization** (most direct): `sudo intel_gpu_top -o - -s 1000` for a116 couple of samples, or interactive `sudo intel_gpu_top`. The **Render/3D**117 (and Blitter/Video) engine busy % should climb well above idle (toward118 ~100%). Requires `intel-gpu-tools` (`sudo apt-get install -y intel-gpu-tools`).119 - **Graphics power rises**: sample `GFXWatt` via turbostat120 (`turbostat --quiet --interval 1 --num_iterations 1 --show PkgTmp,PkgWatt,GFXWatt 2>/dev/null || true`)121 or the `monitor-power-thermal` skill — `GFXWatt` should rise above its idle122 value under GPU load and fall when the run stops.123 - **Workers hold the render node**: `sudo fuser -v /dev/dri/renderD128` should124 list `stress-ng-gpu` PIDs attached to the device (proves attachment, not125 work — pair with one of the signals above).126 - If none of these move while GPU workers are "running", the load is not127 reaching the iGPU (software fallback); note it and treat the run as CPU-only.1288. Capture a post/steady-state snapshot using the same reads as Step 2 (for bounded runs after completion; for open-ended runs, one sample a few seconds in).129130## Validation131Validation section is criteria-only. Do not render the pass/fail results table here.132- Preconditions passed (script executable; `stress-ng` present; no pre-existing stress-ng instance).133- `cpus`, `load`, `gpu`, and `duration` validated against their ranges/syntax.134- A Planned Load table was rendered unconditionally before the confirmation gate.135- Confirmation gate outcome recorded as one of: `confirmed`, `auto_confirm`, `declined`, `dry_run_only`.136- Launch only occurred when the outcome is `confirmed` or `auto_confirm`.137- After launch, `pgrep -x stress-ng` shows the expected activity (one or more workers).138- For bounded runs (`duration` set), the script exited with code `0` at completion.139- For open-ended runs, the PID(s) and stop instructions were reported to the user.140141## Rollback142- Stop an open-ended run at any time: `sudo pkill -x stress-ng` (or Ctrl-C in the launching terminal).143- Stress load is transient and leaves no persistent state; stopping the process fully restores idle behaviour.144- If a power profile was applied via `set-power-profile` before stressing, the profile persists (runtime-only) until reboot regardless of the stress run.145146## Safety Rules147- Do not launch if another stress-ng instance is already running (respect the script's own guard) — stacking stressors skews load and any power measurements.148- Warn before an **open-ended** (no `duration`) high-load run on thermally constrained or fanless enclosures; recommend a bounded `duration` and monitoring temperature (see `pt_mon.sh`).149- Do not run with `sudo` (stress-ng needs no root here); only use `sudo` for the documented `pkill` stop command.150- Do not launch GPU workers (`gpu > 0`) as a way to interfere with a live display/compositor workload without the user's awareness.151- Never mask a failing precondition (missing stress-ng, existing instance) as success.152153## Expected Result Summary154Render the report as the following tables.155156### Run Metadata157158| Field | Value |159|---|---|160| Preconditions | PASS/FAIL |161| Host | `<uname -m>` + CPU model name |162| CPU workers | `<cpus>` of `<NCPU_MAX>` |163| Per-CPU load | `<load>%` |164| GPU workers | `<gpu>` (0 = off) |165| Duration | `<duration or 'until stopped'>` |166| Dry run only | `true` / `false` |167| Confirmation | `confirmed` / `auto_confirm` / `declined` / `dry_run_only` |168169170### Launch Result171172(omit when the outcome is `declined` or `dry_run_only`)173174| Field | Value |175|---|---|176| Command | `stress_gen.sh --cpus <n> --load <p> --gpu <g> [--duration <d>]` |177| Mode | `synchronous (bounded)` / `background (open-ended)` |178| stress-ng PID(s) | `<pids or n/a>` |179| Exit code | `<code or 'running'>` |180| Stop command | `sudo pkill -x stress-ng` |181182### Load Snapshot (pre → during/post)183184| Metric | Before | During/After |185|---|---|---|186| loadavg (1m) | `<value>` | `<value>` |187| PkgTmp (°C) | `<value or n/a>` | `<value or n/a>` |188| PkgWatt (W) | `<value or n/a>` | `<value or n/a>` |189| GFXWatt (W) | `<value or n/a>` | `<value or n/a>` |190191### GPU Load Verification192193(only when `gpu > 0`; omit when the outcome is `declined` or `dry_run_only`)194195| Signal | Idle / Before | Under Load | Verdict |196|---|---|---|---|197| iGPU engine busy % (`intel_gpu_top`) | `<value or n/a>` | `<value or n/a>` | loaded / software-fallback / n/a |198| GFXWatt (turbostat) | `<value or n/a>` | `<value or n/a>` | rose / flat / n/a |199| Render node holders (`fuser`) | — | `<stress-ng-gpu PID count or n/a>` | attached / none |200201### Validation Results202203| Check Area | Status | Evidence | Notes |204|---|---|---|---|205| script executable | PASS/FAIL | `test -x` result | |206| stress-ng present | PASS/FAIL | `command -v stress-ng` | install hint on FAIL |207| no pre-existing instance | PASS/FAIL | `pgrep -x stress-ng` | list PIDs on FAIL |208| input range/syntax | PASS/FAIL | cpus/load/gpu/duration checks | |209| stressor active | PASS/FAIL/N/A | `pgrep -x stress-ng` after launch | N/A when not launched |210| iGPU actually loaded | PASS/FAIL/N/A | engine busy % / GFXWatt rise / render-node holders | N/A when `gpu = 0`; FAIL = software fallback |211| bounded run completed | PASS/FAIL/N/A | exit code | N/A for open-ended |212213### Failures and Troubleshooting214215| Failed Check | Raw Evidence | Troubleshooting Note |216|---|---|---|217| `<check area>` | `<snippet>` | `<action>` |218219## Troubleshooting Notes220- `stress-ng: command not found`: install it with `sudo apt-get install -y stress-ng` (Debian/Ubuntu) and re-trigger.221- "stress-ng is already running": another instance is active. Stop it with `sudo pkill -x stress-ng` (confirm with the user first), then re-trigger.222- **Verify the iGPU is actually loaded** (a running GPU worker is not proof — it223 can fall back to software rendering). In order of directness:224 - `sudo intel_gpu_top` (from `intel-gpu-tools`) — the **Render/3D** engine busy225 % should climb toward ~100% under load. Near-0% while workers run = fallback.226 - `GFXWatt` in `pt_mon.sh` / turbostat should rise above idle and drop when227 the run stops.228 - `sudo fuser -v /dev/dri/renderD128` should list `stress-ng-gpu` PIDs holding229 the render node (confirms attachment; pair with one of the signals above to230 confirm real work).231- GPU workers show little effect: confirm an Intel render node exists (`ls /dev/dri/renderD*`) and that the build of stress-ng includes the `gpu` stressor (`stress-ng --gpu 1 --timeout 2s` should succeed); otherwise use `--gpu 0` and stress CPU only.232- To watch the effect under load, run [tools/power-tuning/pt_mon.sh](../../tools/power-tuning/pt_mon.sh) in another terminal (PkgTmp/PkgWatt), remembering that `SysWatt` may read `0.00` on platforms with a frozen psys counter.233- To combine with a power cap, apply a profile first via the `set-power-profile` skill, then run this skill with a bounded `duration` to observe sustained (PL1) vs burst (PL2) behaviour.234- An open-ended run keeps the CPUs busy indefinitely; always provide a `duration` for automated/unattended use so it self-terminates.235236## Related Skills237- **monitor-power-thermal** — run in another terminal to record PkgTmp/PkgWatt/GFXWatt while this load runs; the two are designed to be paired.238- **set-power-profile** — apply a package/platform power cap or named profile first, then stress to see how the limit holds under load.239- **Typical loop:** apply a limit/profile → start `monitor-power-thermal` → run this skill with a bounded `duration` → read the min/mean/max summary.