PersianDB
A GPU database engine written in Rust and CUDA, running queries end-to-end on the graphics card

A database that keeps its data on the graphics card and answers queries there, without copying it back to the CPU first.
What it is
Most GPU-accelerated tools take your data, move it to the GPU, compute, and move the answer back. That transfer is usually the whole cost.
PersianDB takes the opposite approach. Columns live permanently in GPU memory, queries run as CUDA kernels there, and the results come back as ordinary rows you can hand to your application. The point is not “it is fast”. The point is that the data never leaves the card — which is what makes it possible to run a real database workload there at all, rather than a batch job.
What it does
- The data lives on the GPU. Because a column has a fixed, known layout and length, the CPU can hand the GPU a pointer to it without copying a single byte.
- Queries are real queries. Filters, projections, sorting and joins — 19 hand-written CUDA kernels — and everything stays resident between queries.
- Memory you choose. One global arena owns all columns. Because the arena is fixed and contiguous, the address of any column is known ahead of time, which is what lets the “stay on the GPU” trick work at all.
- Change data without stopping. Compacting a growing column copies only the bytes that actually moved — a million appends moves a million entries, not the whole column.
- Writes are deliberately honest. Inserts and updates go through the CPU, and the code says so rather than pretending otherwise. What this engine is built for is the read side, where the volume is.
The numbers
Measured on my own machine, with the numbers published in the project’s benchmark report rather than quoted from anywhere:
| 2.98 B | rows/s, median — bulk scan over 5 million rows |
| 1.68 ms | wall clock for that whole scan |
| 30.5 M | rows/s sustained insert throughput |
| 61,700 | lines of Rust and CUDA |
| 708 | automated tests, all passing |
Read the bulk scan number with care, and here is why. 2.98 billion rows per second sounds like a claim about query speed. It is not. It is a throughput figure for reading rows, and reading rows is the one thing a memory bandwidth measurement is good at. The honest framing is the one in the report: 85.6% of the scan time goes to synchronisation overhead, not to memory. Real queries take on the order of 700 ns per row.
That gap between “three billion rows a second” and “700 nanoseconds per row” is not a flaw in my reporting — it is the actual state of the thing, and a reader deserves both numbers. An earlier version of this page quoted a figure for a binary that did not exist; that one was wrong, and it is gone.
Why it’s worth a look
Three things here are genuinely difficult and genuinely reusable:
Predictable memory, or the idea collapses. The entire “keep it on the GPU” approach depends on a column’s address being known before the query runs. That means one fixed arena, no fragmentation, and no reallocation. It also means a capacity limit, which is a real trade-off, not a bug.
A stable binary layout, so Python can use it without a copy. I exposed the whole engine to Python through PyO3, which only works if the memory layout is defined and frozen. That constraint is what makes the interface possible — the interface forced the layout, not the other way around.
Bugs you only find by looking. The most interesting bug in this project was a tokenizer that accumulated
counts in a non-associative floating-point type. Each split of a vocabulary was mathematically correct in
isolation, but because floating-point addition does not regroup, vocab_size came out different between two
runs on the same file. Nothing crashed. The numbers were simply not reproducible. Finding that kind of thing is
most of what engineering is.
Current state
Stated plainly, because a résumé that hides this is not worth reading:
- Bulk reads and filtering work and are benchmarked.
UPDATEandDELETEcurrently return success without changing anything. They are not implemented. This is the most important thing to know about the project.- The columnar path is not being written to. The engine is not yet the system of record for anything.
- Benchmarks are machine-specific. They were run here, on one GPU, and they will not reproduce on yours.
There is a patent application covering the GPU-resident execution architecture — currently in the examination stage.

