BLAS bindings for MoonBit (Accelerate/OpenBLAS)
moon add mizchi/blas// Matrix multiplication: C = A @ B
let a = [1.0, 2.0, 3.0, 4.0] // 2x2 matrix
let b = [5.0, 6.0, 7.0, 8.0] // 2x2 matrix
let c = [0.0, 0.0, 0.0, 0.0] // result
@blas.sgemm(a, b, c, 2, 2, 2)
// c = [19.0, 22.0, 43.0, 50.0]// Create C-side buffers (zero-copy after initialization)
let bufs = @blas.mlp_buffers_create(batch_size, input_dim, hidden_dim, output_dim)
@blas.mlp_buffers_init(bufs, input, weight1, bias1, weight2, bias2)
// Forward pass (all computation in C memory)
@blas.mlp_forward_fused(bufs)
// Get output
let output = Array::make(batch_size * output_dim, 0.0)
@blas.mlp_buffers_get_output(bufs, output)
// Cleanup
@blas.mlp_buffers_free(bufs)let bufs = @blas.mlp_train_buffers_create(batch_size, input_dim, hidden_dim, output_dim)
@blas.mlp_train_buffers_init_weights(bufs, weight1, bias1, weight2, bias2)
// Single call does forward, backward, and parameter update
let (loss_sum, correct_count) = @blas.mlp_train_step(bufs, batch_input, batch_labels, learning_rate)
@blas.mlp_train_buffers_free(bufs)just # check + test
just bench # run benchmark
just docker-build # build Linux container
just docker-test # test on Linux
just docker-bench # benchmark on Linuxoptions(
link: { "native": { "cc-link-flags": "-framework Accelerate" } },
)options(
link: { "native": { "cc-link-flags": "-lopenblas -llapack -lm" } },
)# Ubuntu/Debian
sudo apt-get install libopenblas-dev liblapack-dev
# Or use Docker
just docker-build
just docker-test#ifdef __APPLE__
#include <Accelerate/Accelerate.h> // macOS system framework
#else
#include <cblas.h> // OpenBLAS
#endif| Platform | Header | Library | Notes |
|---|---|---|---|
| macOS | <Accelerate/Accelerate.h> | -framework Accelerate | System default |
| Linux | <cblas.h> | -lopenblas -lm | Requires libopenblas-dev |
| Backend | Time/epoch | vs Pure MoonBit |
|---|---|---|
| Pure MoonBit CPU | 130s | 1x |
| BLAS batch | 0.7s | 186x |
pub type FloatBuffer Int64#deprecated("Use `struct T(A)` to declare a newtype and use `.0` access the underlying type instead.")
fn FloatBuffer::inner(self : FloatBuffer) -> Int64pub type IntBuffer Int64pub struct MlpBuffers {
input : FloatBuffer
weight1 : FloatBuffer
bias1 : FloatBuffer
hidden : FloatBuffer
weight2 : FloatBuffer
bias2 : FloatBuffer
output : FloatBuffer
batch : Int
input_dim : Int
hidden_dim : Int
output_dim : Int
}pub struct MlpTrainBuffers {
weight1 : FloatBuffer
bias1 : FloatBuffer
weight2 : FloatBuffer
bias2 : FloatBuffer
input : FloatBuffer
hidden : FloatBuffer
output : FloatBuffer
probs : FloatBuffer
grad_w1 : FloatBuffer
grad_b1 : FloatBuffer
grad_w2 : FloatBuffer
grad_b2 : FloatBuffer
delta2 : FloatBuffer
delta1 : FloatBuffer
labels : IntBuffer
result : FloatBuffer
batch : Int
input_dim : Int
hidden_dim : Int
output_dim : Int
}fn layer1_fused(input : FloatBuffer, weight : FloatBuffer, bias : FloatBuffer, output : FloatBuffer, batch : Int, in_dim : Int, out_dim : Int) -> Unitfn layer2_fused(input : FloatBuffer, weight : FloatBuffer, bias : FloatBuffer, output : FloatBuffer, batch : Int, in_dim : Int, out_dim : Int) -> Unitfn mlp_buffers_create(batch : Int, input_dim : Int, hidden_dim : Int, output_dim : Int) -> MlpBuffersfn mlp_train_buffers_create(batch : Int, input_dim : Int, hidden_dim : Int, output_dim : Int) -> MlpTrainBuffersfn mlp_train_buffers_get_weights(bufs : MlpTrainBuffers, weight1 : Array[Float], bias1 : Array[Float], weight2 : Array[Float], bias2 : Array[Float]) -> Unitfn mlp_train_buffers_init_weights(bufs : MlpTrainBuffers, weight1 : Array[Float], bias1 : Array[Float], weight2 : Array[Float], bias2 : Array[Float]) -> Unitfn mlp_train_step(bufs : MlpTrainBuffers, input : Array[Float], labels : Array[Int], lr : Float) -> (Float, Int)fn sgemm_direct(a : FloatBuffer, b : FloatBuffer, c : FloatBuffer, m : Int, n : Int, k : Int) -> UnitBLAS bindings for MoonBit (Accelerate/OpenBLAS)