Skip to content

fix(im2col): enable the V_SHIFT_V im2col path for non-64-aligned columns (native-dim vision)#57

Merged
booth-algo merged 1 commit into
mainfrom
fix/im2col-shift-native
Jun 2, 2026
Merged

fix(im2col): enable the V_SHIFT_V im2col path for non-64-aligned columns (native-dim vision)#57
booth-algo merged 1 commit into
mainfrom
fix/im2col-shift-native

Conversation

@booth-algo

@booth-algo booth-algo commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

The V_SHIFT_V im2col path (asm_templates/im2col_asm.py, opt-in via CONV_USE_SHIFT=1) already loads each patch at its exact pixel_col, so the K patch elements land at [0:K] of the loaded vector and are placed with a mask + right-shift. The only thing blocking it for SmolVLM2/SigLIP patch embedding (stride=16 → non-64-aligned pixel columns) was a stale compiler-side assertion requiring every ow*stride to be 64-aligned. That assertion predated the emulator's byte-block HBM gather (dma::transfer_mx_from_hbm, #62), which now walks each load one 64-byte block at a time and clamps each read to a block boundary — so a non-64-aligned H_PREFETCH_V start is loaded correctly with no realignment needed. Removing the assertion is the entire fix; there is no emulator change.

Verified on SmolVLM2 vision (1 layer, both im2col modes) across all native dims — allclose 100% PASS in every cell, and the shift path is both smaller and lower modeled latency:

config mode ISA lines sim_lat allclose
16/16/4 no-shift (default) 2,369,505 54.855ms PASS
16/16/4 shift 2,092,822 (−12%) 54.138ms (−1.3%) PASS
32/32/4 no-shift 599,202 39.826ms PASS
32/32/4 shift 335,688 (−44%) 39.120ms (−1.8%) PASS
64/64/16 no-shift 321,664 3.812ms PASS
64/64/16 shift 84,047 (−74%) 3.165ms (−17%) PASS
256/256/64 no-shift 317,805 5.649ms PASS
256/256/64 shift 79,804 (−75%) 4.996ms (−12%) PASS

The reduction is largest where the patch-embed im2col is a big share of the program (64/256: −74/−75% lines, −12/−17% sim_lat) and smaller at mlen=16 (−12% lines) where attention/projection dominate the 2.4M-line program — but it is a win on both axes everywhere. Still opt-in: the default stays im2col_asm_no_shift; CONV_USE_SHIFT=1 selects the shift path. This branch is rebased on main (post #56), so the mlen=16 row compiles via the O(n²) ISA-emit fix.

…mns (native-dim vision)

The shift im2col already loads each patch at its exact pixel_col (patch at [0:K]) and places it with mask + right-shift; only a stale compiler-side assertion required pixel_col to be 64-aligned. That assertion predated the emulator's byte-block HBM gather (dma::transfer_mx_from_hbm, #62), which now walks the load one 64-byte block at a time and handles non-64-aligned starts. Removing the assertion lets the shift path (CONV_USE_SHIFT=1) run for stride-16 patch embedding. Verified: SmolVLM2 vision 64/64/16 1L emulates with allclose 100% PASS. No emulator change. Still opt-in (default stays im2col_asm_no_shift).
@booth-algo booth-algo force-pushed the fix/im2col-shift-native branch from d38a66b to f037c35 Compare June 2, 2026 23:09
@booth-algo booth-algo merged commit 4b8a2cb into main Jun 2, 2026
3 checks passed
@booth-algo booth-algo deleted the fix/im2col-shift-native branch June 2, 2026 23:17
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.

1 participant