Hi @weiji14! Nice to hear rumi came up in your talks, thanks for that
. Yes it is a evolution of some initial ideas we put in TACOTIFF 
Yes, there is SIMD in there, and most of the speed comes from how the codecs are designed around it. Planar is the easiest one to show, so let me go step by step because it’s a fun trick.
The predictor is x = W + N - NW. When you decode, it looks serial, because to get pixel i you need pixel i-1 (the W). So at first sight you would decode one pixel at a time.
But if you move W to the other side you get
x[i] - x[i-1] = r[i] + N[i] - N[i-1]
The right side only uses the residual and the row above, and the row above is already decoded! So you can compute it for the whole row at once. Call it c.
Small example. The row above is 10 12 15 15 and the residuals are 1 0 -1 2.
Step 1, compute c for every pixel at the same time (at the left edge W and NW are zero)
c = 11 2 2 2
Step 2, run a prefix sum over c
x = 11 13 15 17
and that’s the decoded row. You can check any pixel with the normal formula and it matches.
Step 1 is plain vector math, 8 pixels per NEON instruction for uint16. Step 2 is a prefix sum inside the register. You shift the vector by 1 lane and add, then by 2 and add, then by 4 and add, and all 8 lanes now hold the running sum. The last lane gets carried into the next vector. So the only serial part left is one add every 8 pixels instead of one every pixel. There are SSE2 and AVX2 versions too, the kernel is here if you want to take a look.
And if you think about it in 2D, the inverse of planar is just a cumsum down the columns and then a cumsum along the rows. That’s two very standard GPU operations, so planar should be easy to move to CUDA.
PFOR is basically bitpacking with exceptions. Each block of 256 values uses one bit width, and the few values that don’t fit keep their high bits in a small side list. The design is heavily inspired by TurboPFor, especially the vertical SIMD layout. The bits are interleaved in 16 byte lanes, so one vector load gives you a slice of every lane, and unpacking is only shift, and, or. No shuffles at all. For 32 bit values the plain C code is enough and the compiler turns it into NEON by itself. Code is here.
About OpenZL on the GPU, I’ve been following their changes for a while. It’s CUDA only for now, nothing for Metal, and nothing in a release yet (v0.2.0 is still the latest). But, on the dev branch there is a ZL_GPU_decompress() entry point in contrib/gpu. It takes a frame that’s already in device memory and builds a decode plan, but it doesn’t run it yet. Only a few standard codecs are wired in, and the only real kernel so far is bf16 float_deconstruct.
The part I like most/I’m quite excited is PivCo-Huffman, which they just added (paper, original repo). It’s a Huffman variant that decodes a whole block using bitmaps and popcounts instead of one code at a time. They have a CUDA proof of concept doing 100 to 190 GiB/s on an A100, and it uses the same bytes as the CPU version. On my M5 with NEON it decoded 2 to 3x faster than the current Huffman in a quick test, same ratio. So one file can be fast on both CPU and GPU. It needs a newer frame format, so we have to wait for the next OpenZL release.
For the GPU side of GeoZL I’m thinking of a plain C API that takes device pointers and a CUDA stream, and then going through DLPack, not tied to torch. Pretty much the path from your part 3 post.
Metal with unified memory would be really cool, I agree. I haven’t seen anyone working on it yet though.
Sorry this got so long, but nobody around me wants to talk about prefix sums! 