Skip to content

[AINode] Build the result TsBlock with numpy instead of appending one value at a time - #19251

Open
kotselidis wants to merge 2 commits into
apache:masterfrom
kotselidis:ainode-vectorise-tsblock-serde
Open

kotselidis wants to merge 2 commits into
apache:masterfrom
kotselidis:ainode-vectorise-tsblock-serde

Conversation

@kotselidis

Copy link
Copy Markdown

Description

The problem

convert_tensor_to_tsblock in iotdb/ainode/core/util/serde.py builds the TsBlock that AINode returns to the DataNode by appending to a bytes object one value at a time (binary += value.tobytes()). Each append copies the whole object, so the conversion is quadratic in the number of output values.

It matters whenever a model returns a value per input point, for example a custom model that scores every point of a series through CALL INFERENCE. Measured in AINode's own environment (2.0.11, Python 3.11) for a 1 x n float64 tensor:

n Before
10,000 0.084 s
20,000 0.32 s
40,000 1.28 s
80,000 17.9 s
160,000 45.0 s

End to end, a CALL INFERENCE that returns 100,000 per-point scores from a custom PyTorch model on a GPU took 10.1 s, of which 9.7 s was this conversion and 0.33 s the model. Results of a few hundred thousand points take minutes and run into dn_connection_timeout_ms, and the DataNode then retries the call.

The change

The function now takes the tensor's columns as a numpy array and builds the same layout from a list of parts joined once:

  • the header (column count, types, position count, encodings) as before;
  • the time column as one bytes(8 * position_count) block, which is what the previous loop wrote (two big-endian int32 zeros per row);
  • each value column as one big-endian ndarray.tobytes().

The output is byte-for-byte the same as before. The new tests/test_serde.py keeps the previous implementation as a reference and compares the two on scalars, 1-D and 2-D tensors, float32, float64, int32, int64 and bool, NaN, infinities and -0.0, a non-contiguous tensor, and a 2 x 20,000 float64 tensor.

After the change, the conversion takes 2 ms for 100,000 values and 5.5 ms for 1,000,000. The CALL INFERENCE above takes 0.34 s instead of 10.1 s.

struct is no longer used and its import is removed; pandas is still used by the type helpers.

Verification

cd iotdb-core/ainode
python -m unittest discover -s tests -p 'test_serde.py'
black --check iotdb/ainode/core/util/serde.py tests/test_serde.py
isort --check-only --profile black iotdb/ainode/core/util/serde.py tests/test_serde.py

Run with AINode 2.0.11's environment (PyTorch 2.9.1), with Black 25.1.0 and isort 6.0.1. I have not run it on the PyTorch 2.14 environment that master's pyproject.toml now pins, nor run the AINode cluster integration tests.


This PR has:

  • been self-reviewed.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Higher-rank tensors are accepted without rank validation, allowing the TsBlock header’s declared position count to differ from the number of serialized values.

1 open issue
What changed in this PR

This PR speeds up AINode inference-result serialization by replacing repeated byte appends with bulk NumPy conversion, targeting quadratic conversion costs for large outputs.

Changes:

  • Builds time and value columns in bulk and joins serialized parts once.
  • Adds byte-equivalence tests across tensor shapes and types, plus a large-output performance check.
  • Removes the unused struct import and corrects the conversion comment.
File Description
iotdb-core/​ainode/​tests/​test_serde.py Adds reference-based serialization tests and a performance regression check.
iotdb-core/​ainode/​iotdb/​ainode/​core/​util/​serde.py Uses bulk big-endian NumPy serialization instead of per-value appends.

Review effort: Balanced

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

@SpriCoder SpriCoder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good Job~

@RkGrit
RkGrit self-requested a review November 13, 2026 16:35
@RkGrit

RkGrit commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

LGTM~

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.

4 participants