Skip to content

[RNE Rewrite] Use std::span instead of raw pointers in native C++ ops + tokenizer cosmetic refactor#1315

Open
msluszniak wants to merge 1 commit into
rne-rewritefrom
@ms/span-ops-tokenizer
Open

[RNE Rewrite] Use std::span instead of raw pointers in native C++ ops + tokenizer cosmetic refactor#1315
msluszniak wants to merge 1 commit into
rne-rewritefrom
@ms/span-ops-tokenizer

Conversation

@msluszniak

@msluszniak msluszniak commented Jul 17, 2026

Copy link
Copy Markdown
Member

Description

Applies the treatment from the FSMN-VAD framing op (#1298) to the remaining native ops that indexed tensor buffers through raw pointers: wrap the buffer in a std::span, take a subspan per row/lane, and use range-based algorithms instead of manual pointer arithmetic.

  • math/operations.cppsigmoid/threshold become std::ranges::transform; softmax/argmax take a per-lane subspan instead of re-deriving offsets from a raw pointer on each access.
  • cv/image_ops.cpp — channel-plane and colormap-pixel access go through subspans; the toChannelsFirst memcpy becomes std::ranges::copy.
  • cv/box_ops.cppdecodeToXyxy takes a std::span<const float, 4> row rather than four loose floats, removing the boxesPtr[idx * 4 + 0..3] unpacking at both call sites.

Byte-level spans are bounded by size_ (bytes) and element spans by numel_, so every subspan is bounds-checked against the real allocation.

cv::Mat constructions that take data_.get() are left as-is: they hand the whole buffer to OpenCV rather than doing pointer math, so a span adds nothing. Core files are untouched, per the issue.

Also drops the five repeated if (!result.ok()) blocks in nlp/tokenizer.cpp in favour of a local unwrap helper, mirroring the one in core/model.cpp (that one is file-local and typed to executorch::runtime::Result, so it cannot be reused for tokenizers::Result).

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)
  • New feature (change which adds functionality)
  • Documentation update (improves or adds clarity to existing documentation)
  • Other (chores, tests, code style improvements etc.)

Tested on

  • iOS
  • Android

Testing instructions

Refactor is behaviour-preserving, and verification so far is compile-only — not yet run on a device.

All four translation units compile clean under the project's strict warning set from .clangd (-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wold-style-cast -Wcast-align -Wshadow -Wdouble-promotion), with no new warnings:

cd packages/react-native-executorch
for f in cpp/extensions/{math/operations.cpp,cv/image_ops.cpp,cv/box_ops.cpp,nlp/tokenizer.cpp}; do
  clang++ -fsyntax-only $(tr '\n' ' ' < compile_flags.txt) -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion "$f"
done

To exercise at runtime: run apps/computer-vision (classification/segmentation/detection cover softmax, argmax, applyColormap, resize, normalize, toChannelsFirst, and nms) and the tokenizer screen in apps/nlp.

Related issues

Closes #1308

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

Additional notes

Applies the treatment from the FSMN-VAD framing op (#1298) to the
remaining native ops that indexed tensor buffers through raw pointers:
wrap the buffer in a span, take a subspan per row/lane, and use
range-based algorithms instead of manual pointer arithmetic.

- math: sigmoid/threshold become std::ranges::transform; softmax/argmax
  take a per-lane subspan instead of re-deriving offsets from a pointer.
- cv/image_ops: plane and pixel access go through subspans; the
  toChannelsFirst memcpy becomes std::ranges::copy.
- cv/box_ops: decodeToXyxy now takes a std::span<const float, 4> row
  rather than four loose floats unpacked at each call site.

Byte-level spans are bounded by tensor size_ (bytes) and element spans by
numel_, so every subspan is bounds-checked against the real allocation.

Also drops the five repeated `if (!result.ok())` blocks in the tokenizer
in favour of a local `unwrap` helper, mirroring the one in core/model.cpp
(that one is file-local and typed to executorch::runtime::Result, so it
cannot be reused for tokenizers::Result).

Closes #1308
@msluszniak msluszniak self-assigned this Jul 17, 2026
@msluszniak msluszniak added the improvement PRs or issues focused on improvements in the current codebase label Jul 17, 2026
@msluszniak msluszniak changed the title [RNE Rewrite] Use std::span instead of raw pointers in native C++ ops [RNE Rewrite] Use std::span instead of raw pointers in native C++ ops + tokenizer cosmetic refactor Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement PRs or issues focused on improvements in the current codebase

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RNE Rewrite] Use std::span instead of raw pointers in native C++ ops

1 participant