Repository navigation
Exp 2026 06 13 Task Batching
Date: 2026-06-13 · Status: ❌ RULED OUT · Path: ork-driver
A transformer fires ~168–197 small matmuls/token, each a separate RKNPU_SUBMIT ioctl paying the ~134 µs round-trip floor. Hypothesis: batching multiple matmuls into one submit (task_number > 1, multiple task_obj_addr entries) would amortize that floor — and this might be how the closed runtime is faster.
-
Commit:
95f2481(oRKLLM/ork-driver) —tools/batch_probe.c+ork_npu_probe_batch. -
Method: time
ntaskidentical small int8 matmuls asntaskseparate ioctls vs one ioctl withtask_number=ntask. -
Build:
make batch_probe && sudo ./batch_probe [ntask] [K] [N].
The core of ork_npu_probe_batch — same task[] array, then (a) ntask separate ioctls vs (b) one ioctl with task_number=ntask:
struct rknpu_task *t = c->task.cpu; /* ntask tasks, same regcmd */
for (int i=0;i<ntask;i++){ memset(&t[i],0,sizeof t[i]); t[i].enable_mask=0xd;
t[i].int_mask=0x300; t[i].int_clear=0x1ffff; t[i].regcfg_amount=108; t[i].regcmd_addr=c->regcmd.dma; }
// ...
double t0=ork_now_us(); /* (a) ntask separate ioctls */
for (int i=0;i<ntask;i++){ sub.task_number=1; sub.subcore_task[0]=(struct rknpu_subcore_task){0,1};
if(ioctl(fd,DRM_IOCTL_RKNPU_SUBMIT,&sub)) return -1; bsync(fd,&O,RKNPU_MEM_SYNC_FROM_DEVICE); }
*us_unbatched = ork_now_us()-t0;
sub.task_number=ntask; sub.subcore_task[0]=(struct rknpu_subcore_task){0,(uint32_t)ntask};
t0=ork_now_us(); /* (b) one ioctl, ntask tasks */
if(ioctl(fd,DRM_IOCTL_RKNPU_SUBMIT,&sub)){ perror("batched SUBMIT"); return -1; } /* <-- TIMES OUT */
bsync(fd,&O,RKNPU_MEM_SYNC_FROM_DEVICE);
*us_batched = ork_now_us()-t0;- The batched ioctl (
task_number>1) TIMES OUT:task counter: 0x0, the NPU dispatches nothing; the kernel soft-resets and recovers. A naivetask[]/ subcore config does not drive multi-task execution. - Premise was also wrong: the closed runtime's captured 12-task submit is one matmul's program (4 sub-tasks × 3 subcores), not multiple matmuls batched. So librkllmrt also does ~1 submit/matmul and pays the same floor (~11 tok/s on 1.7B, which ork-driver matches).
This is a kernel-level submit probe, not model inference, so the tok/s standard doesn't apply (per the methodology, probe experiments report the probe result). Re-confirmed on RK3588:
$ sudo ./batch_probe 2
batched SUBMIT: Connection timed out
submit-batching probe (single core, int8 896x896):
ntask=2 rc=-1 (wedge/dims)
ntask=2 batched into one RKNPU_SUBMIT → the ioctl times out (-1), the NPU dispatches nothing. The kernel rejects naive multi-task submits; result is stable across runs.
❌ Ruled out twice over: the kernel rejects naive cross-matmul batching, and the reference runtime doesn't use it. The per-matmul submit floor (~134 µs ioctl/IRQ) is inherent hardware, not a lever. Decode multi-core already overlaps the 3 cores (207 µs vs 350 µs single).