Skip to content

Releases: hbofz/NeSLE

v0.3.1: verified numbers

Choose a tag to compare

@hbofz hbofz released this 01 Sep 19:40

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.md quoted throughput 6x below the README's own headline, with
    no indication it was historical.
  • docs/benchmark-gpu-vs-cpu.md predates the entire optimization program and
    now carries a banner naming the specific corrections.
  • KNOWN_ISSUES.md carried superseded A100 figures and claimed the C++ tests
    were not in CI; they have been since 394d090.
  • MANIFEST.in omitted scripts/*.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.md splits the platform-specific build detail out of the README.
  • Discussions enabled.

NeSLE v0.3.0 - the scaling release

Choose a tag to compare

@hbofz hbofz released this 01 Sep 19:40

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

Choose a tag to compare

@hbofz hbofz released this 01 Sep 19:40

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

Choose a tag to compare

@hbofz hbofz released this 01 Sep 19:40

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.