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.3 is the current release, and it still moves: behaviour can change between releases — see CHANGELOG.md. A companion gem to CArray, it follows CArray's surface, which is not settled until CArray 3.1.
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.2, < 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: the gap it fills beside CArray, the subset a block is written in, and where a kernel gets its data
- Getting started — the block, its extents, what the three methods return, and where a kernel stands beside
a + b * candCArray.fuse - The shapes a kernel takes — work that reaches no neighbour, extents and subscripts, stencils, reductions, and contraction over a repeated index
- Supported features — locals and types, branches, raising, the types that are not just a number, calling C, and the recognized subset with what it refuses
- Compiling, caching and inspecting — what the first call costs, where kernels are kept, reading the generated C, the
carray-jitcommand, and what the suite checks - Design notes — decisions that were not obvious, and why
- Cheatsheet — the eight
jit_methods andCArray.fuseon one page, to look up rather than to read - 31 exercises, with solutions — thirty-one small tasks in the order this guide introduces things, each with its solution and what it answers (日本語)
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