ADRStablesince v0.4.0

ADR-011: Canonical hashing for models and datasets

Every non-trivial engineering decision in NeuronScope carries an ADR — context, decision, alternatives, consequences, status. This is the ADR that governs fingerprints.

Audience: Contributors, adopters evaluating stabilityRead: 9 minEdit on GitHub Source

Status

  • Number: ADR-011
  • Status: Accepted (superseded parts of ADR-004)
  • Deciders: Core maintainers
  • Date accepted: 2024-08-19
  • Applies to: neuronscope.fingerprint and every adapter that produces canonicalizable inputs

Context

Fingerprints are the primitive every other NeuronScope guarantee depends on. If a fingerprint is unstable across machines, comparisons are silently meaningless. If it is too aggressive, every trivial change (e.g. renaming a buffer) invalidates cached recordings. We need a canonicalization scheme with three properties: deterministic across supported platforms, insensitive to observationally irrelevant changes, and cheap enough to run at record time for large models.

Decision

  1. Use BLAKE3 as the hash function. It is faster than SHA-256, keyed variants are available for namespacing, and it is portable across every architecture we support.
  2. Canonicalize model parameters in parameter-name order, not module traversal order. Parameter names are stable under module refactoring; traversal order is not.
  3. Cast every tensor to a fixed endianness before hashing. Read the raw bytes; do not go through a Python-level iterator.
  4. Include buffers (running statistics, RNG) in the model digest. Exclude optimizer state and hooks.
  5. For streaming datasets, hash the schema and generator identity, not the materialised rows. A separate MaterialisedDataset canonicalizer exists for the finite case.
  6. Every canonicalizer carries a version. Bumping it is a breaking change and is only allowed on a major release.

Alternatives considered

  • SHA-256. Rejected on speed. On a 7B-parameter model, SHA-256 dominates record-time overhead by roughly 3× vs BLAKE3.
  • Module-traversal order. Rejected because module refactors that preserve semantics would change the digest.
  • Hashing tensor repr. Rejected because repr is platform-dependent for floating-point tensors and truncates long tensors.
  • Row-content hashing for streaming datasets. Rejected because it forces materialisation and defeats the purpose of streaming.

Consequences

  • Cross-machine caching is safe: two machines with the same environment fingerprint produce the same artifact fingerprints byte-for-byte.
  • Users who observe a fingerprint change on upgrade should read the release notes; the canonicalizer version bump will be called out.
  • Streaming dataset users cannot verify materialised content via the fingerprint alone — they must use MaterialisedDataset or attach a checksum out-of-band.

Compliance

A dedicated test suite (tests/fingerprint/test_stability_matrix.py) runs on every supported platform in CI and asserts that a fixed reference model produces a fixed reference fingerprint. A failure blocks release.

Related