Remix.run Logo
cpa 2 hours ago

For those wondering what it's for: it's basically NumPy + a JIT compiler with standard Haskell syntax (you mostly just need to change the type signatures, not the code).

It can vectorize, parallelize on the CPU, or offload to the GPU automatically.

It's a very mature project, maybe 10+ years old.

Athas an hour ago | parent [-]

One big difference compared to NumPy (which you may or may not care about depending on how picky you are), is that Accelerate is a higher-order programming model. Basically, you can have 'map' (with a user-provided function), and it will go fast, in contrast to NumPy's model where only first-order operations go fast.

mccoyb 39 minutes ago | parent [-]

Can you say a bit more about this?

In particular, compare you JAX’s vmap — one model for vmap is that it is a program transformation on first order functions, that returns a first order function (“function” is a bit wonky here: but it’s JAX’s Jaxpr representation), but vmap itself is not a primitive in the Jaxpr language.

Is the same true here about map (can I think of it like vmap)? Or is it true that I can define higher order functions and Accelerate will handle them? What about functions with recursion?

Thanks! If you happen to see this - Futhark is very cool.

Athas 15 minutes ago | parent [-]

I wrote a bit about this some years ago: https://futhark-lang.org/blog/2020-05-03-higher-order-parall... - but note that Jax isn't subject to these constraints; it's more like Accelerate and Futhark.

I'm not a Jax expert. Accelerate's 'map' allows for almost arbitrary sequential code - there is some fine print, because it's an embedded language, and the biggest fine print is that nested parallelism is not allowed. You can define your own Haskell-level higher order functions, and Accelerate will handle them just fine, because essentially all the Haskell-level computation is "compiled away" (by being run) before the Accelerate code is JIT-compiled at run-time. You can consider Haskell to be a meta-language in which you ultimately construct Accelerate program terms, and then those are compiled and run - not too dissimilar from how Jax does it, actually.

Recursion works, but for an uninteresting reason: the recursion is on the Haskell side, and will essentially be unrolled before Accelerate gets its hand on it. This allows you to do some fun things (like partially evaluating a ray tracer on its scene description), but it's often not what you want, and Accelerate provides some combinators (that look like higher-order Haskell functions) for expressing sequential looping/