Skip to content

Asynchronous dispatch / op batching on Metal and CUDA: per-op launch cost dominates small workloads #28

Description

@vyncint

Measured (oxmega device-bench, M4 Pro, 100 epochs, 1,356 rows × 45)

workload CPU Metal
mlp-h16 BCE, 1 seed 0.30 s 1.77 s
mlp-h16 BCE, 3 stacked seeds 0.54 s 2.16 s
mlp-h16 set-NLL, 3 seeds 0.82 s 6.5 s
linear-lag5 set-NLL, 3 seeds 0.86 s 6.9 s

Batching three seeds into one graph cut Metal's per-op count 3× and it is still 4–8× slower than the CPU: every op is a synchronous command buffer (wait_until_completed per dispatch) and every AdamW parameter update is several tiny ops. CUDA has the same shape (one stream, synchronous downloads).

Proposal

  • Encode many ops into one command buffer / stream and synchronise only at to_device(Cpu)/to_vec (lazy completion), keeping the current per-op semantics as the observable contract.
  • Fused optimizer step kernels (AdamW over a parameter list in one launch).
  • Measure with the table above; the device-bench in vyncint/oxmega is a ready-made benchmark.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions