Repository navigation
Releases: hbofz/NeSLE
Release list
v0.3.1: verified numbers
No emulator or kernel changes. This release is about making the project's claims
checkable and the repository contributable.
Every published number re-measured
All five A100 throughput claims were re-measured from a clean clone and
reproduced at or above their published values. Two independent runs, on a
40 GB and an 80 GB A100, agreed to within 0.3%.
| Envs | Previously published | Measured | Verdict |
|---|---|---|---|
| 4,096 | 311,844 | 310,903 | PASS |
| 16,384 | 1,050,710 | 1,108,937 | PASS |
| 32,768 | 1,931,460 | 2,004,806 | PASS |
| 65,536 | 3,142,205 | 3,267,050 | PASS |
| 131,072 | 2,816,144 | 3,055,618 | PASS |
69/69 tests pass and all three falsifiability checks pass on the same run. Raw
output is committed at docs/data/verification-2026-09-01-a100.json.
Measured for the first time:
- Crossover at 8 environments, not the 32 and 64 the docs claimed. Both
figures predated the 2026-07-29 optimization program. - Device memory of ~195 KB per environment, 12.2 GiB at the 65,536-env
peak. This confirms a "13 GB" figure the README had asserted with no
measurement behind it. - Linear scaling holds to ~8,192 envs, not ~2,048 as documented.
Reproduce it yourself
benchmarks/verify_claims.py reuses the functions in benchmarks/gpu_vs_cpu.py,
so the protocol matches the published tables exactly. It prints a
claimed-vs-measured table and exits non-zero if any claim, test, or check fails.
Run it directly, through notebooks/verify_claims.ipynb on Colab, or on a
rented GPU via the Colab CLI.
Corrected
Stale numbers were traced to the commit that wrote them and fixed:
- The nes-py comparison read 269x, computed against an intermediate build. It
is ~1,370x. docs/design.mdquoted throughput 6x below the README's own headline, with
no indication it was historical.docs/benchmark-gpu-vs-cpu.mdpredates the entire optimization program and
now carries a banner naming the specific corrections.KNOWN_ISSUES.mdcarried superseded A100 figures and claimed the C++ tests
were not in CI; they have been since 394d090.MANIFEST.inomittedscripts/*.py, so sdists shipped without the build
script the README tells users to run.- A vendored doc cloned a repository name that no longer exists.
Contributing
CONTRIBUTING.md: setup, the checks to run, and the bar for emulator and
performance changes.- Nine issues filed and labelled, each pointing at a specific file. The largest
is mapper support beyond NROM (#5), which would take NeSLE from a Mario
trainer to a general NES RL platform. docs/install.mdsplits the platform-specific build detail out of the README.- Discussions enabled.
NeSLE v0.3.0 - the scaling release
One evening after v0.2.0: the docs/gpu-scaling.md optimization program executed end to end. Every number below is measured; every abandoned direction has published measurements.
Headline (verified, clean clone, 69/69 tests + falsifiability on both platforms)
- A100-SXM4-80GB: 3,142,205 env-steps/s peak at 65,536 envs (12.6M NES frames/s, ~209,000x real-time; ~14,300x that VM's CPU) - 4.5x v0.2.0.
- GTX 1050 Ti: 180,437 env-steps/s at 4,096 envs (576x CPU) - 5.1x v0.2.0.
- Training behavior bit-exact: fixed-seed PPO losses identical to pre-sprint to 4 decimal places.
What did it
- Table-driven 6502 decode replacing the 151-case opcode switch (verified: 8M-instruction differential harness vs the old core, zero divergence; cycle-exact Klaus counts) + forced inlining of the render chain after the larger module tripped nvcc's inline heuristics.
- Lazy PPU settlement: the PPU advances only at event horizons instead of every instruction (supersedes the planned CuLE-style kernel split, which the register-resident design made obsolete).
- Hot-path hygiene: restrict-qualified SoA pointers, dead-guard removal, merged frame-position word.
What was tried and retired, with data
- Zero page in shared memory: 1.9x regression on sm_61 (occupancy collapse from 32 to 6 warps/SM) - implementation preserved on a branch, verdict in docs/gpu-scaling.md.
- Wavefront/opcode-binned dispatch: measured 3.2x SLOWER than thread-per-env on realistic instruction streams (prototype + full methodology committed under benchmarks/wavefront_prototype/) - hardware SIMT reconvergence over the table-driven core already shares dispatch work; explicit binning serializes it.
docs/gpu-scaling.md is now a complete ledger: every tier shipped or closed with measurements.
Requirements: CUDA GPU (CTK 12.x for Pascal), Python >= 3.10, user-supplied SMB ROM (never distributed).
NeSLE v0.2.0 - verified at scale
Second release, one day after v0.1.0. Everything below is measured, not projected.
Headline numbers (fresh, this release's HEAD)
- A100-SXM4-80GB: 699,456 env-steps/s peak at 65,536 parallel envs (~2.8M NES frames/s, ~46,000x real-time); 161,430 at 4,096 envs = ~746x that machine's CPU. Verified from a clean clone with 69/69 tests green.
- GTX 1050 Ti: 35,488 env-steps/s at 4,096 envs (110x CPU) - +20% over v0.1.0 from this release's optimization pass.
- vs the standard CPU stack (nes-py): ~269x on identical hardware.
Correctness
- Renderer now draws from a vblank-frozen presentation snapshot with a two-region scroll split (SMB's status bar) - eliminates the object-pop / HUD-loss / ghost-content artifacts that affected all recordings (render-only; training was never affected). Object-pop events: 130 -> 21 on a scripted A/B.
- Fixed a use-after-free in the DLPack device-view bindings (tensor could outlive the GPU memory it pointed at).
- Fixed checkpoint resume semantics (--total-timesteps is now cumulative) and resumed-run fps reporting.
Performance work (measured per-change, docs/gpu-scaling.md)
- PPU hot-state register caching: +17% stepping.
- Vectorized bulk copies (snapshot/reset/DMA): +9.5% stepping.
- Hybrid render dispatch: 2.9x faster small-batch rendering (recording/eval).
- Research note with code-level divergence/memory analysis, CuLE et al. survey, and a ranked redesign roadmap (tiers 1-3 open).
Tooling & docs
- Cross-platform CUDA build: python scripts/build_cuda_extension.py (Windows MSVC auto-detection; Linux include fix found on Colab).
- C++ tests now run in CI; smart-reward magnitudes exposed as CLI flags; native-checkpoint eval/recording tool with artifact-aware filtering (examples/native_ppo_eval.py).
- Honest results throughout: the trained 1-1 agent clears the level occasionally (best episode recorded in the README GIF); the 8-world curriculum agent reaches mid-level everywhere but captures no flags. Training checkpoints from the A100 experiments are preserved outside the repo.
Requirements: CUDA GPU (CTK 12.x for Pascal), Python >= 3.10, user-supplied SMB ROM (never distributed).
NeSLE v0.1.0 - first publication-ready release
GPU-native NES emulator + reinforcement-learning stack for Super Mario Bros.
Highlights
- CUDA-batched NROM emulator: one GPU thread per env; 29,491 env-steps/s at 4,096 envs on a GTX 1050 Ti (88x a single-env CPU baseline, measured 2026-07-28); ~560k env-steps/s recorded on A100 (RAM obs, 128 envs).
- GPU-resident PPO (nesle.native_ppo): observations, rollouts, GAE, and optimizer all on device via DLPack; --reward-mode smart runs a dense shaped Mario reward entirely on GPU.
- Snapshot reset from 8 bundled save states (worlds 1-8); curated 11-action mario action space.
- 68 tests (GPU/ROM-dependent ones auto-skip); CI on Ubuntu py3.10/3.12; clean-clone install verified on Windows 11 + Pascal.
Requirements: CUDA GPU (CTK 12.x for Pascal), Python >= 3.10, user-supplied SMB ROM (not distributed).
See README for quickstart, docs/ for architecture and benchmark reports, KNOWN_ISSUES.md for honest limitations.