carray-jit
JIT compilation of CArray kernels written in Ruby.
This library was written to make explicit, cell-by-cell work on CArray arrays fast. A subset of Ruby chosen for numerical computation is JIT-compiled and evaluated as a C-level loop over CArray arrays: a cell that reads its neighbours, a recurrence, a loop written out. The aim is to combine that with CArray's already fast vectorized arithmetic and reductions, and so speed up numerical computation with CArray as a whole.
The block is read with Prism, translated to C if it falls inside that subset, compiled with the system C compiler and called through Fiddle. The compiled object is cached on disk, so a kernel is compiled once.
Status
0.1.4 is the current release, and it still moves: behaviour can change between releases.
Features
- A JIT compiler for C-level loops. A block becomes one C function over CArray's own memory, built by the system C compiler and called through Fiddle.
-
Ordinary Ruby, and enough of it. The source is parsed with Prism -- no DSL, no
eval-- and every operation means what Ruby means by it, apart from the order a reduction takes its terms in. The subset is enough to state a numerical algorithm; what falls outside it is refused by name and line, not run as a Ruby loop. -
A method for each shape.
jit_forfor recurrences and loops written out,jit_stencilfor windows at any rank,CArray.jit_contractfor contraction over a repeated index, or over every index the result's axes do not name,jit_eachandjit_mapfor a pass that reaches no neighbour,jit_initfor filling an array from its own indices. - View- and mask-aware. Columns, transposes and slices of slices are written in place without a copy, and masks propagate as CArray propagates them.
-
Pure C functions, in and out.
jit_externbinds one from a library and a kernel calls it by address;jit_functioncompiles one from a block and hands back a C function pointer. -
The backend for
CArray.fuse. An array expression compiles instead of being walked a node at a time, without being asked and without changing the answer. - Compiled once, across processes. The shared object is cached on disk and reused by later runs.
Install
gem install carray-jit
Or add it to your Gemfile:
gem "carray-jit"Requires:
- Ruby >= 3.2
- CArray >= 3.0.4, < 3.1
- A C compiler
- Prism and Fiddle (both ship with Ruby; Fiddle is a bundled gem)
Example
# Legendre polynomials at x = 0.5, by the recurrence that defines them.
# No array expression states this: P[i] needs P[i-1], which the same
# loop has just written.
x = 0.5
legendre = CArray.double(24)
legendre[0] = 1.0 # P_0(x) = 1
legendre[1] = x # P_1(x) = x
CArray.jit_for(2...24) { |i| # i is the loop index: 2, 3, ... 23
w = x * legendre[i-1] # a block local; its type is inferred
wy = w - legendre[i-2] # reaching back two cells
legendre[i] = wy + w - wy/i # the cell this pass writes
}
legendre[0..5].to_a
# => [1.0, 0.5, -0.125, -0.4375, -0.2890625, 0.08984375]The jit_ methods are this gem's, and exist once require "carray/jit" has run. An expression over whole arrays wants CArray.fuse, which is CArray's own and needs no compiler -- and gets compiled anyway where this gem is loaded.
Documentation
- Introduction — what carray-jit is and what it is for
- Getting started — a first kernel, step by step
- The shapes a kernel takes — loops, stencils, reductions and contractions
- Supported features — what a block may contain
- Compiling, caching and inspecting — compilation, the kernel cache and the generated C
- Design notes — why things are the way they are
- Cheatsheet — every method on one page
- Exercises — 31 small tasks, each with its solution
- Language reference — the block language, construct by construct
Contributing
Bug reports and feature requests are welcome — please open an issue.
Before opening a pull request, read CONTRIBUTING.md. It is short, and it says which form a contribution is best sent in. A small, self-contained bug fix is fine as a pull request. Anything larger is better started as an issue: code here gets rewritten as a matter of course, so a patch for a larger change is likely to end up reimplemented rather than merged, and describing the problem gets you further than writing one.
Credits
carray-jit is created and maintained by himotoyoshi. The author provided the design; the implementation was written with AI coding tools and has been verified primarily through the test suite and practical use.
License
MIT