Show HN: Eyot, A programming language where the GPU is just another thread

Published: (March 8, 2026 at 07:04 AM EDT)
5 min read

Source: Hacker News

Overview

Eyot is a new language I’m building to make offloading work to the GPU as seamless as spawning a background thread.

Eyot source code is transparently compiled for both CPU and GPU, with communication between the two handled by the runtime. Traditional GPU programming expects you to handle many tasks—memory allocation, compiling the kernel, scheduling work, etc. These have long been handled by a language runtime when writing code for the CPU, and Eyot extends that convenience to code destined for the GPU as well.

The intended users are those in areas where the GPU or other accelerators are used heavily, e.g. game development, numerical analysis, and AI.

It is early days for Eyot. It is not ready for real work, but you can experiment with it, and if you do, I’d love to hear your thoughts. To take a simple example (available in the playground):

fn square(value i64) i64 {
   print_ln("square(", value, ")")
   return value * value
}

cpu fn main() {
    // 1. call it directly
    print_ln("square(2) on cpu = ", square(2))

    // 2. call it as a worker running on cpu
    let cpu_worker = cpu square
    send(cpu_worker, [i64]{ 3 })
    print_ln(receive(cpu_worker))

    // 3. call it as a worker running on the gpu
    let gpu_worker = gpu square
    send(gpu_worker, [i64]{ 4, 5, 6 })
    print_ln(receive(gpu_worker))
}
  • The square function is called as you’d expect, directly, and on the CPU.
  • A CPU worker is created from the square function (let cpu_worker = cpu square). This worker processes values sent to it with the send function on a background CPU thread. After squaring the number, the worker returns it through the call to receive.
  • This time a GPU worker is created rather than a CPU worker (let gpu_worker = gpu square). This causes the square function to be compiled as a kernel and run on the GPU; otherwise it acts identically. As you can see, Eyot’s print_ln works GPU‑side.

Motivation

I’ve worked on many projects where shifting computation to the GPU presented an obvious path to better performance that got ignored due to the difficulty of doing so. These projects were not just in obvious areas like computer vision or game development, but also in unlikely matches for GPU programming, like desktop application development.

For example, back when I worked on Texifier, a macOS LaTeX editor, I adjusted the venerable TeX typesetting system to output polygons directly into GPU memory rather than writing a PDF. This reduced latency enough that we could update the output in real time. The feature was popular, but the difficulty of making it work left me questioning whether the project was worth it.

With Eyot I want to build a language where working on the GPU is ingrained so deeply in the language’s design that it becomes trivial. For a long time we have thought about the CPU/OS combination as something that runs our code, rather than a device to be manipulated. Eyot simply extends this to the GPU. Options like CUDA already exist, but with Eyot the intention is to build the entire language around that model of GPU concurrency.

Current status

Progress is slow as I work on this in my spare time (sponsors appreciated!), and I’ve recently had a break with the arrival of a new baby. My major roadmap items are:

  • Rendering – Eyot currently facilitates access to the GPU for computational purposes only. Game development is a big target, so rendering support is high on my wishlist. I’m hoping to do this using Vulkan and simultaneously replace OpenCL in favour of Vulkan compute.
  • Syntax – I’ve deferred development of Eyot’s syntax so I can experiment with the CPU/GPU interaction without adding language features that would not be viable in both cases. Major missing syntax features are algebraic data types, lambdas, and some form of interface/trait‑style polymorphism.
  • GPU memory management – Vectors and strings can only be allocated CPU‑side; this should also work on the GPU. I’d also like the memory manager to be able to transparently shift allocations to shared buffers when appropriate.
  • Performance – Following the principle “Make it work, make it right, make it fast”, I will probably leave this for the immediate future, but it would be nice to throw real workloads at Eyot soon and get them up to speed.
  • Standard library – The current library contains only a handful of functions; it needs to be started.

Things I will not be working on

  • Automatic parallelisation – Eyot does not, and will not, automatically parallelise work across CPU/GPU cores. The intention is to be a convenient option for distributing work across processors, not to reduce control.
  • Theoretically optimal performance – Eyot is not intended as a total replacement for current GPGPU libraries any more than C/C++ are intended as total replacements for assembly. Significant performance deviations between Eyot code and equivalent C/Vulkan code would be considered bugs, but ease of use is an acceptable price to pay for some performance penalties.
  • Being the next great general‑purpose language – There will be as few syntax differences between GPU and CPU as possible, so the language design will be bound by GPU capabilities, which may restrict what can be added to Eyot’s syntax.

Further reading

Thanks for reading. You can learn more about Eyot from its documentation and source code. If you want to try it out, feel free to open an issue or drop a comment!

0 views
Back to Blog

Related posts

Read more »