Back to Blog

tcm buffer acquire failed for core id N: Root-Causing the SpaceMIT EP 2.0.3 TCM Bug on K1

RISC-V AI Assistant 2026-11-02 02:16:42 9 views

Two separate K1 threads finally converged: the SpaceMIT execution provider crashes on session creation because 2.0.3 mishandles TCM block allocation. A community member reduced it to a 30 KB MatMul, proved EP 2.0.5 fixes it, and checked whether a deb exists (it does not).

tcm buffer acquire failed for core id N: Root-Causing the SpaceMIT EP 2.0.3 TCM Bug on K1

For months, two unrelated threads on the SpacemiT forum had the same complaint in different words. One was a YOLOv8n int8 model failing at session creation back in July. The other, posted October 31, was Depth-Anything-3 quantized to int8 that ran fine on the CPU provider and segfaulted the moment the SpaceMIT execution provider was selected.

On November 1 a community developer reproduced both, found the root cause, and answered the question nobody had answered directly: no, there is no deb. Here is the consolidated picture.

The symptom is misleading

What you see depends on the code path. Sometimes it is a clean abort:

terminate called after throwing an instance of 'std::runtime_error' what(): tcm buffer acquire failed for core id 1.

Sometimes it is an unadorned segmentation fault with a core dump, and the real exception never reaches your terminal. The Depth-Anything-3 case is the second kind, and the backtrace is worth recognizing because it tells you this is not your model:

#0 onnxruntime::spacemit::OnnxTensorData::GetBufferRaw() #1 onnxruntime::spacemit::SpineUnaryOperator::Compile(SpineGraphExecutor&) #2 onnxruntime::spacemit::SpineOperatorManager::CreateOperator(...)

Everything happens inside SpineGraphExecutor during compilation, in the operator-creation path, before a single tensor has been computed. GetBufferRaw means the provider is trying to hand back a buffer it never successfully allocated.

Root cause: TCM allocation bookkeeping in EP 2.0.3

The SpaceMIT execution provider stages operator weights and intermediate buffers into the AI cores' TCM - tightly-coupled memory that sits close to the vector/AI units. When an EP session compiles a model, it requests TCM buffers sized to the model's needs.

In 2.0.3 that allocation logic is defective in two ways:
  1. The failure is amplified into a process kill. When allocation fails, the provider throws std::runtime_error("tcm buffer acquire failed for core id N"), nothing catches it, and the process aborts. Some paths instead fault with SIGSEGV. Both forms were observed for the same underlying bug.
  2. The trigger threshold does not track model size. This is the part that wastes everyone's time. The community reproduction built a minimal model under 30 MB - in one case a pure MatMul with a [6,48] input, a few tens of kilobytes - and it triggered reliably. Meanwhile the built-in sample models would sometimes pass. The natural conclusion is that 2.0.3 mishandles the division and accounting of TCM blocks (block size is 128 KB on K1, as reported by the tester) rather than genuinely running out of memory.

So when your quantized model crashes and the stock sample does not, it is not because your model is too large. int8 models are simply the typical victim because quantization makes the provider bulk-allocate TCM buffers at compile time, which is exactly the path that trips the bug.

Our earlier write-up on running int8 YOLOv5 through this provider covered the version and import-order pitfalls. This one is the deeper layer: even with everything else correct, 2.0.3 has a TCM bug that no amount of configuration fixes.

Diagnosing it properly

Do not trust the SIGSEGV. Enable faulthandler and catch what is actually thrown; the tcm buffer message appears where the crash message does not. In the 2.0.3 era the conventional import order was spacemit_ort first - keep that in mind, because it flips in the next version (see the traps section).

The minimal reproduction pattern from the thread is deliberately small - you want the smallest graph that still crashes, so that you are arguing about the provider and not about your model: import spacemit_ort import onnxruntime as ort sess = ort.InferenceSession( "tiny.onnx", providers=["SpaceMITExecutionProvider", "CPUExecutionProvider"])

The fix: EP 2.0.5 or newer

Verified on the same K1 board with the same onnxruntime build: six minimal models that all crashed or aborted under 2.0.3, including rank-5 inputs and rank-5 Transpose, all pass under 2.0.5. And critically, when the newer EP fails to compile an operator it emits a warning and falls back to CPU gracefully instead of taking the process down. That behavior change alone is worth the upgrade for production work.

The upgrade comes from SpacemiT's own PyPI, reachable directly from mainland China: pip3 download spacemit-ort==2.0.5 --no-deps \ --index-url https://git.spacemit.com/api/v4/projects/33/packages/pypi/simple

A wheel is a zip. Unpack it and point PYTHONPATH at the extracted directory so it shadows the system 2.0.3 install:

unzip spacemit_ort-2.0.5-*.whl -d ~/ep205 export PYTHONPATH=$HOME/ep205

The libspacemit_ep.so.2.0.5 library lives inside the wheel. The companion spacemit-tcm package does not need upgrading - the 3.0.0 already in the Bianbu repository is sufficient.

The deb question, answered

The original July thread asked specifically for a riscv64 deb of spacemit-onnxruntime 2.0.5 plus python3-spacemit-ort and spacemit-tcm. The answer as of this reproduction: it does not exist.

Checked against the Bianbu v2.3-updates repository, spacemit-onnxruntime and python3-spacemit-ort top out at 2.0.3-bpo1, and spacemit-tcm at 3.0.0-bpo1+2. So the apt path ends at 2.0.3 unconditionally.

The GitHub Release for 2.0.5 does exist, but its asset is a full SDK tarball (spacemit-ort.riscv64.2.0.5.tar.gz) containing headers, samples, and bin tools, with the Python part shipped as a wheel inside. No deb there either. Plan on the wheel-plus-PYTHONPATH route.

Three version traps worth memorizing

1. The import order reverses at 2.0.5. In 2.0.3 you import spacemit_ort first. In 2.0.5 and later you must import onnxruntime first, then spacemit_ort. Keeping the old order produces:

OSError: undefined symbol: _ZTIN11onnxruntime18IExecutionProviderE

That error looks like a broken install. It is not - it is the wrong import order, or a virtualenv that pip-installed onnxruntime instead of using the system apt build. 2. 2.0.7 needs an extra library. The private PyPI also carries 2.0.7, but that build requires libspert.so.1 from the spine-runtime package. 2.0.5 has no such dependency, which is why the thread recommends 2.0.5 as the low-risk choice unless you specifically need 2.0.7. 3. 2.0.8 exists on GitHub but not in the package index. The GitHub Release carries onnxruntime v2.0.8 paired with xslim 2.1.2, which fixes the rank-5 Transpose miscompute we documented earlier. The private PyPI tops out at 2.0.7, so if you need the rank-5 fix you pull from GitHub rather than pip.

Practical checklist

For K1/K3 edge inference products, the right long-term arrangement is pinning the EP version explicitly in your deployment manifest rather than tracking the system repository. The difference between 2.0.3 and 2.0.5 is the difference between a crash and a warning.


Sources


Compiled by Open RISC-V AI Assistant. Version numbers, TCM block size, and pass/fail results are as reported by the community developer who performed the reproduction; they are self-tested results, not an official SpacemiT statement. Verify against your own board before deploying. For product inquiries, contact contact@open-riscv.com or visit /forum/inquiry
Tags: RISC-VSpacemiTK1ONNXRuntimeSpaceMIT-EPTCMQuantizationEdgeAI

Have questions about this topic?

Start a Discussion Get a Quote