Skip to the content.

The Banana Pi BPI-SM10 is a Pico-ITX board around the SpacemiT K3 SoC (CoM260 / COM3K316128…): 8× X100 general-purpose cores (RVA23, RVV 1.0, VLEN=256) plus 8× A100 AI cores (IME2, VLEN=1024, up to 60 TOPS), integrated IMG PowerVR BXM-4-64 GPU (Vulkan 1.3 / OpenCL 3.0). Ours runs Bianbu 4.0.6 with EESSI on dev.eessi.io/riscv.

Sponsored by Banana Pi — this board was provided by Banana Pi. Product page: BPI-SM10 (K3-CoM260) · docs.

X100 vs A100

K3 is two asymmetric RISC-V clusters. Both implement RVV 1.0 (A100 is not scalar-only); the AI cores trade general-purpose behaviour for a wider vector unit and IME2. Device-tree: spacemit,x100 (cpu@0–7) vs spacemit,a100 (cpu@8–15).

  X100 (cores 0–7) A100 (cores 8–15)
Role General-purpose CPU AI / matrix (IME2)
Clock (typ.) up to 2.4 GHz up to 2.0 GHz
Clusters 0–1 (cluster_cpus 0–3, 4–7) 2–3 (cluster_cpus 8–11, 12–15)
ISA (hart) rv64imafdcvh + bitmanip / vector crypto rv64imafdcv (no h) + same vector ext. family
Hypervisor yes (h) no
RVV yes — VLEN=256 (vlenb=32, measured) yes — VLEN=1024 (vlenb=128, measured on cpu8)
Custom — IME2 · up to 60 TOPS (vendor matrix path)
Default Linux scheduling yes — normal SMP fenced — online in sysfs, but not in a normal task’s affinity mask

Plain RVV on A100 is often slower than on X100 without vendor IME2 code — wide VLEN is there for the matrix path, not as a drop-in “faster X60.”

Getting onto A100 (/proc/set_ai_thread)

SpacemiT’s kernel keeps general threads on X100 even when A100s are idle. Stock taskset -c 8 fails with EINVAL until the thread is registered as an AI thread:

echo $$ > /proc/set_ai_thread   # world-writable on Bianbu; unlocks cores 8–15 for this TID
taskset -c 8-15 …               # now affinity works; process stays on A100 for its lifetime

On our board /proc/set_ai_thread is mode 0222 (write-only). After the write, Cpus_allowed_list becomes 8–15 (X100 is no longer available to that task).

VLEN pitfall: do not start on X100 (VLEN=256), let ld.so cache vector decisions, then migrate to A100 (VLEN=1024) — that pattern can SIGSEGV. Prefer set_ai_thread before exec of the real binary (same pattern as k3_taskset / SpacemiT’s AI runtimes).

For mixed MPI jobs (e.g. HPL), ranks on A100 each echo $TID > /proc/set_ai_thread then pin to cores 8–15 before exec. Equal rank counts are a poor fit for HPL — see heterogeneous balancing below.

Compute paths on this board

All four paths we care about are present — and the Custom / GPU story differs from K1 (X60 IME1 / BXE-2-32).

Compute backends on the Banana Pi BPI-SM10 (SpacemiT K3)

Path On SM10 / K3
Scalar X100 — rv64gc baseline under RVA23
Vector X100 RVV 1.0 · Zvl256b (same VLEN class as X60)
Custom A100 cluster — IME2 matrix path · 60 TOPS (VLEN=1024)
GPU BXM-4-64 — the SKU SpaceMiT’s proprietary OpenCL/Vulkan DDK actually targets (unlike K1’s BXE)

Per-board diagrams for the other machines: VisionFive 2 · Orange Pi RV2 · Banana Pi F3. Homepage logo is the combined view.

Status

Board is on the desk and reachable over SSH with CVMFS + EESSI (EESSI_VERSION_OVERRIDE=2025.06-001, software tree riscv64/generic). eessi_archdetect reports SpacemiT X100. Default user threads only see cores 0–7; A100 work needs /proc/set_ai_thread.

HPL (OpenBLAS RVV)

See also the HPL app overview.

EESSI foss/2025b + HPL/2.3, FlexiBLAS → local OpenBLAS 0.3.34. Two RVV targets matter on K3:

OMP_NUM_THREADS=1 unless noted, NB=192, residual checks PASSED.

Single-cluster baselines (N=12000, 8 ranks, 2×4)

Cluster OpenBLAS target GFLOP/s Result
X100 only ZVL256B 52.0 PASSED
A100 only ZVL256B (VLEN-safe) 15.0 PASSED
A100 only ZVL1024B 35.9 PASSED

A100 ZVL1024B is ~2.4× the portable-ZVL256B A100 HPL rate (~1.45× slower than X100, vs ~3.5× before). Stock NETLIB on A100 was ~0.8 GFLOP/s @ N=4000.

A100 ZVL1024B at smaller N: 22.5 GF @ N=4000, 30.4 GF @ N=8000 (both PASSED).

Equal 16-rank mixed (8+8), same BLAS everywhere

Ranks 0–7 on X100, 8–15 on A100 (set_ai_thread), 4×4 grid:

N BLAS on A100 GFLOP/s Result
4000 ZVL256B 16.2 PASSED
8000 ZVL256B 23.7 PASSED
12000 ZVL256B 27.5 PASSED
12000 ZVL1024B (X100 still ZVL256B) 57.5 PASSED

With ZVL256B on both clusters, equal ranks stall on slow A100 work. With ZVL1024B on A100, equal 8+8 becomes the best mixed config and beats X100-only.

Heterogeneous X100 + A100 (N=12000)

Per-rank FlexiBLAS: X100 → OPENBLAS_DUAL (ZVL256B), A100 → OPENBLAS_ZVL1024B. Wrap: HPL_NX100, HPL_A100_THREADS, set_ai_thread + taskset.

Config Ranks Grid A100 OMP GFLOP/s Result
8 X100 + 8 A100 × 1 8 + 8 4×4 1 57.5 PASSED
8 + 4 × 2 8 + 4 3×4 2 56.2 PASSED
8 + 2 × 4 8 + 2 2×5 4 55.5 PASSED
8 + 1 × 8 8 + 1 3×3 8 47.6 PASSED
X100 only (ref.) 8 2×4 — 53.2 PASSED

(Earlier ZVL256B-everywhere hetero peaked at 51.3 GF with 8+2×4; A100 ZVL1024B flips the optimum to equal 16 ranks.)

IME2 (int8 GEMM)

Same smt.vmadot opcode as the X60, different tile. On the A100 (VLEN=1024) one instruction is 8×8×16 int8→int32. Harness: benchmarks/ime (ime2_bench.c), core 8 after /proc/set_ai_thread, userspace 1.800 GHz. Bit-exact against the scalar reference. GOP/s is 2·M·N·K / t, median of 15 reps. Full includes packing.

M×N×K RVV int8 IME2 compute IME2 full full / RVV
512×512×512 7.58 102.5 91.6 12.1×
768×768×512 7.52 109.1 103.3 13.7×
1024×1024×512 7.38 64.2 61.8 8.4×

The crest is 768×768×512, then 1024×1024×512 drops, the same shape as the X60 IME1 table once the working set leaves L2. At that 768 shape the X60 full GEMM peaks at 42 GOP/s (1.6 GHz).

The same binary with IME off, one X100 at 2.000 GHz: RVV int8 15.9 GOP/s on all three shapes. Plain RVV on the A100 is slower than on the X100. That RVV column is the untuned widening-dot baseline, not a tuned GEMM.

llama.cpp

Eight A100 cores, llama-bench -p 128 -n 32, use_ime2: 1. Full tables, the 10 Q4_0 models, and the 17 Q4_K_M models are on the llama.cpp page.

File Prompt Decode Decode peak
Qwen2.5 0.5B Q4_0 525.96 38.78 58.67 at 4 cores
Qwen2.5 0.5B Q3_K_M 499.23 47.95 8 cores
TinyLlama 1.1B Q2_K 254.37 43.39 8 cores

X100 RVV on the Q4_0 file is 193.68 / 41.95. Nine of the ten Q4_0 models are coherent. Qwen2.5 3B Q4_0 repeats one character. All 17 Q4_K_M models are coherent. The BXM-4-64 GPU is still unmeasured.

ONNX Runtime

Eight A100 cores, Qwen2.5-0.5B int4, accuracy_level=4. Prompt is 128 copies of token 151644; decode is 32 tokens. Fork k3-a100-ime2. Full notes: ONNX Runtime.

  4 cores 8 cores
Prompt 235.94 390.72
Decode 34.09 33.77

One core, K=4096 N=11008: M=1 35 GOP/s, M=4 85.6, M=128 86. This is a different kernel from the llama.cpp Q4_0 row above.

vLLM

Stock X100 CPU backend, seven worker threads, bfloat16, eager, ten small models. SmolLM2 135M is prompt 1.95 t/s and decode 1.27 t/s. The same prompts with int4 linears on Ime2HpGemm, eight A100 cores: SmolLM2 135M prompt 87.11 t/s and decode 11.14 t/s. One core, the larger FFN shapes are about 37 GOP/s at M=1 and 93–95 at M=4. Full tables: vLLM.