Skip to content

perf(lang-core): bulk copyToFloatArray for MmapFloatTensorData - #1362

Merged
michalharakal merged 1 commit into
developfrom
perf/mmap-bulk-copy
Oct 17, 2026
Merged

michalharakal merged 1 commit into
developfrom
perf/mmap-bulk-copy

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Problem

MmapFloatTensorData didn't override copyToFloatArray(), so it used the TensorData default. That walks every element through get(*indices): an IntArray copy for the vararg spread plus a boxed Float per element.

RMSNormalization.eagerFusedRmsNorm copies its gain tensor on every forward, and with MAPPED weights the gains are MmapFloatTensorData. In a BitNet b1.58 2B4T JVM decode profile, this was the top allocation site once the Vector API fallback was fixed (#1360): about 10 GB in a 45 s window. It also showed up in CPU samples as MmapFloatTensorData.calcFlatIndex.

Change

An override that does one bulk read:

override fun copyToFloatArray(): FloatArray {
    val out = FloatArray(shape.volume)
    val view = floatBuffer.duplicate()   // the shared view's position stays untouched
    view.position(0)                     // separate statements: Android's pre-Java-9 nio returns Buffer
    view.get(out)
    return out
}

It copies exactly shape.volume floats in row-major order, which is the same contract as the default. apiCheck passes.

Tests

New MmapFloatTensorDataCopyTest (lang-core jvmTest, 3 tests):

  • the bulk copy equals the element-wise get order for a rank-3 tensor;
  • only volume floats are copied from a larger buffer;
  • a slice at a nonzero byte offset (the way MmapTensorSource slices) copies correctly, the shared floatBuffer.position() stays 0, and the copy is repeatable.

:skainet-lang:skainet-lang-core:jvmTest passes 1046/1046.

Measured

Arduino Ventuno Q, 4× Cortex-A78C, JVM, BitNet 2B4T I2_S, 128 greedy tokens, backported onto 0.61.0:

  • the TensorData.copyToFloatArray ← MmapFloatTensorData ← eagerFusedRmsNorm element-wise site disappears from JFR. MmapFloatTensorData.copyToFloatArray remains only as one bulk array per call (~3.8 % of allocation);
  • greedy output is byte-identical (md5 52f57d1d…);
  • decode goes 2.33 → 2.36 tok/s (within noise; on the JVM this is an allocation fix rather than a wall-time one).

Possible follow-up: cache the gain in RMSNormalization so even the bulk copy happens once.

Refs #1357

🤖 Generated with Claude Code

MmapFloatTensorData inherited TensorData.copyToFloatArray, which walks every element
through get(*indices) — an IntArray copy for the spread plus a boxed Float each.
RMSNormalization.eagerFusedRmsNorm copies its (mmap'd) gain every forward, so in a
BitNet 2B4T JVM decode this was ~10 GB of allocation per 45 s. Override with one
bulk FloatBuffer read (duplicate, so the shared view's position is untouched;
statements kept separate for Android's pre-Java-9 nio).

Refs #1357

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

📖 Documentation Preview

The documentation has been built successfully for this PR.

Generated Files:

  • Operator documentation: docs/modules/operators/_generated_/
  • JSON schema output: operators.json

Artifacts:

  • Download the documentation-preview-1362 artifact to view the complete documentation locally.

This comment will be updated automatically when the PR is updated.

@michalharakal
michalharakal merged commit 58bda6e into develop Oct 17, 2026
19 checks passed
@michalharakal
michalharakal deleted the perf/mmap-bulk-copy branch October 20, 2026 12:01
michalharakal added a commit that referenced this pull request Oct 21, 2026
CHANGELOG [0.62.0] - 2026-10-21 with the parity headline over #1363, #1364,
#1368, #1369, #1426, #1427, #1428 and #1430, plus entries for the operator
coverage matrix (#1370), the BitNet decode allocation and threading fixes
(#1359, #1360, #1361, #1362), the ClassificationSupport extraction (#1429)
and the toolchain bumps (Kotlin 2.4.21, kotest 6.2.6, Gradle 9.8.1).
VERSION_NAME, CITATION, Antora version, README bom coordinate, What's New
and contributors, Android tutorial coordinates; regenerated operator and
kernel-support matrices; SKEEP-007 rollout step 3 marked shipped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant