SPB Git

spb/forge Public MIT

Forge — LLM training from scratch in pure C++20 + Metal on Apple Silicon.

C++ 61.2% C 23% Python 7.6% TeX 7.2% CMake 1.1%
1.4 KB · 29 lines
Raw Blame History
1// Author: Simon-Pierre Boucher — contact@spboucher.ai2//3// Embedding gather + scatter-grad. ids are i32. Forward: one thread per4// (token, channel). Backward: one thread per (row, channel) accumulating5// with device atomic_float — repeated tokens collide, so order is6// nondeterministic (sum of floats); deterministic mode routes embedding7// backward through the CPU reference instead.8#include <metal_stdlib>9using namespace metal;1011kernel void embedding_fwd_f32(device const float* W   [[buffer(0)]],12                              device const int*   ids [[buffer(1)]],13                              device float*       out [[buffer(2)]],14                              constant uint&      C   [[buffer(3)]],15                              uint2 gid [[thread_position_in_grid]]) {16    // gid.x = channel, gid.y = token index17    out[ulong(gid.y) * C + gid.x] = W[ulong(ids[gid.y]) * C + gid.x];18}1920kernel void embedding_bwd_f32(device const int*     ids  [[buffer(0)]],21                              device const float*   dout [[buffer(1)]],22                              device atomic_float*  dW   [[buffer(2)]],23                              constant uint&        C    [[buffer(3)]],24                              uint2 gid [[thread_position_in_grid]]) {25    const float g = dout[ulong(gid.y) * C + gid.x];26    atomic_fetch_add_explicit(&dW[ulong(ids[gid.y]) * C + gid.x], g,27                              memory_order_relaxed);28}29