Why l (new runtime for k and q)

Lobsters Hottest Tools

Summary

A new runtime for the K and Q programming languages that reimagines execution using SIMD, parallelism, fusion, and compression to better leverage modern hardware.

<p><a href="https://lobste.rs/s/wkm8tk/why_l_new_runtime_for_k_q">Comments</a></p>
Original Article
View Cached Full Text

Cached at: 07/21/26, 08:39 AM

# Why l. | l Source: [https://lv1.sh/blog/why-l/](https://lv1.sh/blog/why-l/) I have been working with K and Q since 2001, nearly twenty\-five years now\. I will say the obvious part first: Arthur Whitney is a genius\. K and Q remain extraordinary languages\. Their design is small, dense, and beautiful\. But despite years of optimization, extension, and correction, the core implementation model is still rooted in Arthur’s original insight from the 1990s\. I did not want to change the language\. I am not arrogant enough to think I should invent a new one\. What I wanted to do was reimagine the implementation for the machines we actually use today\. Computers in 2026 are not the computers of 1997\. CPUs are wider\. Memory is relatively slower\. Every machine has multiple cores\. Many have GPUs, NPUs, AMX units, NEON, AVX, VNNI, and other specialized execution engines\. The hardware has changed dramatically\. The programming model has not kept up\. l is my attempt to keep the language, K, Q, qSQL, IPC, the whole world of existing code, and rebuild the execution engine underneath it\. The implementation is built around four ideas:**SIMD, parallelism, fusion, and compression**\. ## SIMD as a first\-class primitive I wanted every operator to take advantage of the hardware automatically\. Before clusters, GPUs, or distributed systems, a simpler question: how fast can every primitive be on a single core? That means making every cycle count\. It means treating SIMD not as an optional optimization but as the default path for primitive execution\. If the hardware can process many values per instruction, the language should use that automatically, no rewrites, no vector intrinsics, no thinking about it\. The primitive should just be fast\. ## Parallelism by default Parallelism has always been natural for array languages\. APL, K, and Q all express work as large, regular operations over arrays, exactly the structure modern CPUs can exploit\. But I wanted to think about it from first principles\. Instead of bolting threads on as an external tool, l treats parallel execution as part of the primitive runtime\. Small arrays stay on the fast single\-core SIMD path\. Larger arrays split across worker threads automatically\. The user never decides when to parallelize; the runtime decides, from the size, shape, and cost of the operation\. And as arrays get larger still, the same idea extends to accelerators\. On a modern Apple machine, many workloads are too small to justify moving data to a GPU, but some are not\. Small values stay on CPU pipelines\. Larger values use threads\. The largest operations move to a GPU, NPU, or other backend when it pays\. You should not need a different version of the language because the hardware changed\. ## Transparent fusion When I wrote K and Q in financial services, the language was usually elegant\. When it became slow, the cause was rarely the primitive itself\. It was intermediate allocation\. You write something beautiful: ``` q) sum sqrt x ``` Conceptually simple: square\-root each value, then sum\. But a traditional implementation may allocate an entire intermediate vector for`sqrt x`, only to consume it immediately in`sum`\. That allocation is waste\. l makes fusion transparent\. The runtime chains primitive operations and eliminates intermediate objects wherever it can\. In`sum sqrt x`, the summing loop consumes the square\-rooted values directly\. Where safe, it modifies temporaries in place\. Where possible, it collapses the whole expression into one pipeline\. You still write normal K or Q\. The implementation makes the obvious thing fast\. ## Compression as a runtime concept The fourth idea, the hardest, and probably the most important, is compression\. It should not be a storage feature off to the side\. It should be a first\-class concept inside the runtime\. An operator should not care whether the object it operates on is compressed\. The runtime should know how to operate on compressed data directly\. For compression, SIMD, threading, and fusion to compose correctly, they have to be designed together\. That is the core implementation challenge\. With few exceptions, most primitives can work directly on compressed data\. A huge vector can stay compressed, move fewer bytes through memory, fit better in cache, and still produce the same result\. > Memory bandwidth is the enemy\. Modern CPUs are incredibly fast\. The bottleneck is rarely arithmetic\. It is moving data: RAM to cache, cache to registers, core to core, CPU to accelerator\. The simplest way to make software faster is to move less data over a shorter distance\. That is why compression is central to l\. If a vector can be represented in fewer bytes, l keeps it that way\. If the data can stay in cache, it stays in cache\. If an operation can execute without decompressing the full vector, it does\. The runtime moves the minimum number of bytes required to compute the correct answer\. ## The guardrail: full K and Q compatibility The guardrail for all of this was compatibility\. I wanted l to be K and Q, not “inspired by K,” not “similar to Q\.” I wanted existing commercial k4 and Q code to run without modification\. I did not want to leave behind more than two decades of code, puzzles, and a community I grew up with\. That means implementing the language, qSQL, IPC, and the surrounding execution model, and taking real code, not just examples, and asking whether it can actually run inside a larger system\. Once you commit to that, the problem becomes much harder, and much more meaningful\. The point of l is not to create a new language and ask people to migrate\. The point is to preserve the language and replace the machinery underneath it\.**Same language\. New engine\.** K and Q gave us one of the most powerful array programming models ever built\. l asks what that model looks like when the implementation is designed for modern hardware from the ground up: SIMD by default, parallel by default, fused by default, and compressed by default\. That is why I built l\.

Similar Articles

l: A new runtime for k and q

Hacker News Top

l is a new runtime for k4, q, and qSQL that provides transparent SIMD, compressed vectors, and automatic parallelism while maintaining full compatibility with existing code. It targets high-performance computing on Wall Street.

QBE – Compiler Back End

Hacker News Top

QBE is a compact, hobby-scale compiler backend that provides 70% of the performance of industrial optimizing compilers in 10% of the code, supporting amd64, arm64, and riscv64 with a simple SSA-based intermediate language.

@elliotarledge: For those wondering why I use a Kimi Linear megakernel instead of Qwen 3.6, first look at the parameter counts. One is …

X AI KOLs Timeline

Elliot Arledge explains why he prefers using a Kimi Linear megakernel over Qwen 3.6 for kernel performance, comparing parameter counts, layer synchronization, hidden dimensions, and architecture-specific optimizations. The discussion highlights that Kimi Linear architecture is more suitable for megakernel implementation, especially for batch-1 decode on RTX PRO 6000 Blackwell.