Skip to content

v0.1.3 — hybrid Metal GROUP BY beats DuckDB CPU on TPC-H

Choose a tag to compare

@singhpratech singhpratech released this 10 May 05:10
3ebcd76

v0.1.2 + new hybrid Metal GROUP BY that flips TPC-H from a loss to a clean win.

The most-attacked benchmark (TPC-H SF10 GROUP BY l_orderkey at 15M unique groups) was 1.78× slower than DuckDB CPU multi-thread in v0.1.2. In v0.1.3 it's 1.30× faster. Combined with the existing multi-aggregate fusion wins, Metal now wins 9 out of 10 TPC-H lineitem operations we ship.

Apple Silicon (M4 Max) vs DuckDB CPU 16-thread

Workload DuckDB CPU mt Metal v0.1.3 Speedup
TPC-H SF10 multi-agg fusion l_quantity 27 ms 1.06 ms 25.5× 🚀
TPC-H SF10 multi-agg fusion l_extendedprice 26 ms 1.18 ms 22.0× 🚀
TPC-H SF10 multi-agg fusion l_orderkey 11 ms 1.13 ms 9.7× 🚀
SF10 SUM l_quantity HOT 5 ms 1.16 ms 4.3×
TPC-H SF10 GROUP BY l_extendedprice (1.35M unique) 113 ms 28.9 ms 3.9×
500M × 1M GROUP BY synthetic 820 ms 242 ms 3.4×
1B × 1M GROUP BY synthetic 2500 ms 770 ms 3.2×
1B int64 SUM HOT 40 ms 16.2 ms 2.6×
SF10 SUM l_extendedprice HOT 5 ms 2.23 ms 2.2×
SF10 SUM l_orderkey HOT 3 ms 1.68 ms 1.8×
🆕 TPC-H SF1 GROUP BY l_orderkey (1.5M unique) 8 ms 5.71 ms 1.40×
🆕 TPC-H SF10 GROUP BY l_orderkey (15M unique) 56 ms 42.95 ms 1.30×
TPC-H SF10 GROUP BY l_quantity (50 unique) 26 ms 372 ms CPU 14× ❌ structural

What's new in the algorithm

Hybrid GROUP BY that auto-dispatches between two paths per query:

  • slot-lock path — 32,768 hash partitions × 1024 threadgroup-memory slots. 32-bit CAS protects non-atomic 64-bit sum updates (workaround for Apple Silicon's missing 64-bit atomic_fetch_add). Sweet spot: expected_groups ∈ [1024, 16M].
  • radix-opt path — vectorized 4× ulong4 loads, in-block 8-bit multi-split scatter via simdgroup prefix-sum, simdgroup-prefix-sum bucket scan. For low or very high cardinality.

Env override: GPUDB_METAL_GROUPBY_PATH=slotlock|radix to force a path.

Quality

  • 96 / 96 C++ unit tests pass
  • 46 / 46 SQL tests pass

Install (Apple Silicon, requires DuckDB ≥ 1.5)

curl -fL -o gpudb.osx_arm64.duckdb_extension \
  https://github.com/singhpratech/duckdbgpumetaldbram/releases/download/v0.1.3/gpudb.osx_arm64.duckdb_extension

duckdb -unsigned -c "LOAD '$(pwd)/gpudb.osx_arm64.duckdb_extension';
                     SELECT gpu_sum(value::BIGINT) FROM range(1000000) AS t(value);"

🤖 Generated with Claude Code