Skip to content

Commit 92287ae

Browse files
romirdesclaude
andcommitted
Add oneDNN matmul-primitive MatMul backend (threadpool runtime)
Second, build-time-selectable oneDNN backend that uses the high-level dnnl::matmul primitive with the THREADPOOL CPU runtime, coexisting with but mutually exclusive from the merged BRGeMM (SEQ ukernel) backend. oneDNN picks the kernel and calls back into gemma.cpp's hwy::ThreadPool through a threadpool_iface adapter for all parallelism. - ops/onednn_matmul.h / -inl.h: engine singleton, HwyThreadPoolAdapter bridge, self-validating reordered-weights cache, thread_local user-managed scratchpad, and DoMatMul_OneDnn with native scale/add/ demote fusion (writes final values straight into C, clean fallback on any failure). - ops/matmul-inl.h: dispatch hook (BF16xBF16, M>1) with fallback to the stock path; MMPerKey bookkeeping field; zones caller label; bench fair-timing for the first JIT+reorder call. - Mutual exclusion enforced at three layers: CMake FATAL_ERROR, Bazel ambiguous-select(), and a C++ #error guard. - CMake + Bazel wiring to fetch/build oneDNN v3.11 (THREADPOOL runtime). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4b26b03 commit 92287ae

11 files changed

Lines changed: 721 additions & 0 deletions

‎BUILD.bazel‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ config_setting(
3434
define_values = {"gemma_onednn_brgemm": "1"},
3535
)
3636

37+
# To enable the OneDNN matmul-primitive backend (threadpool runtime), build with:
38+
# bazel build --define gemma_onednn_matmul=1 ...
39+
# This is mutually exclusive with gemma_onednn_brgemm: passing both --defines
40+
# makes the select()s below match two conditions at once, which Bazel rejects
41+
# with an "ambiguous select" error -- the intended failure mode, mirroring the
42+
# CMake FATAL_ERROR and the #error guard in ops/onednn_matmul.h.
43+
config_setting(
44+
name = "gemma_onednn_matmul",
45+
define_values = {"gemma_onednn_matmul": "1"},
46+
)
47+
3748
cc_library(
3849
name = "basics",
3950
srcs = ["util/basics.cc"],
@@ -363,12 +374,16 @@ cc_library(
363374
hdrs = [
364375
"ops/brgemm.h",
365376
"ops/matmul.h",
377+
"ops/onednn_matmul.h",
366378
],
367379
defines = select({
368380
":gemma_onednn_brgemm": [
369381
"GEMMA_ONEDNN_BRGEMM=1",
370382
"DNNL_EXPERIMENTAL_UKERNEL",
371383
],
384+
":gemma_onednn_matmul": [
385+
"GEMMA_ONEDNN_MATMUL=1",
386+
],
372387
"//conditions:default": [],
373388
}),
374389
deps = [
@@ -384,6 +399,7 @@ cc_library(
384399
"@highway//:profiler",
385400
] + select({
386401
":gemma_onednn_brgemm": ["@onednn"],
402+
":gemma_onednn_matmul": ["@onednn_tp//:onednn"],
387403
"//conditions:default": [],
388404
}),
389405
)
@@ -395,6 +411,7 @@ cc_library(
395411
textual_hdrs = [
396412
"ops/brgemm-inl.h",
397413
"ops/matmul-inl.h",
414+
"ops/onednn_matmul-inl.h",
398415
],
399416
deps = [
400417
":allocator",
@@ -412,6 +429,7 @@ cc_library(
412429
"@highway//:profiler",
413430
] + select({
414431
":gemma_onednn_brgemm": ["@onednn"],
432+
":gemma_onednn_matmul": ["@onednn_tp//:onednn"],
415433
"//conditions:default": [],
416434
}),
417435
)
@@ -433,6 +451,7 @@ cc_library(
433451
"ops/brgemm-inl.h",
434452
"ops/matmul_static-inl.h",
435453
"ops/matmul-inl.h",
454+
"ops/onednn_matmul-inl.h",
436455
],
437456
deps = [
438457
":allocator",
@@ -449,6 +468,7 @@ cc_library(
449468
"@highway//:timer",
450469
] + select({
451470
":gemma_onednn_brgemm": ["@onednn"],
471+
":gemma_onednn_matmul": ["@onednn_tp//:onednn"],
452472
"//conditions:default": [],
453473
}),
454474
)

‎CMakeLists.txt‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
3333
# Enable with: cmake -DGEMMA_ONEDNN_BRGEMM=ON ...
3434
option(GEMMA_ONEDNN_BRGEMM "Enable OneDNN BRGeMM micro-kernel for MatMul (x86-64)" OFF)
3535

36+
# Optional: OneDNN matmul primitive via the threadpool runtime (x86-64 only).
37+
# Enable with: cmake -DGEMMA_ONEDNN_MATMUL=ON ...
38+
option(GEMMA_ONEDNN_MATMUL "Enable OneDNN matmul primitive (threadpool runtime) for MatMul (x86-64)" OFF)
39+
40+
# oneDNN's CPU runtime (SEQ vs THREADPOOL) is a whole-library compile-time
41+
# choice, so the two oneDNN backends cannot share one oneDNN build.
42+
if(GEMMA_ONEDNN_BRGEMM AND GEMMA_ONEDNN_MATMUL)
43+
message(FATAL_ERROR
44+
"GEMMA_ONEDNN_BRGEMM and GEMMA_ONEDNN_MATMUL are mutually exclusive: "
45+
"oneDNN's CPU runtime (SEQ for BRGeMM vs THREADPOOL for the matmul "
46+
"primitive) is a whole-library compile-time choice. Enable only one.")
47+
endif()
48+
3649
if(EMSCRIPTEN)
3750
add_compile_options("-sMEMORY64")
3851
add_compile_options("-msimd128")
@@ -113,6 +126,24 @@ if(GEMMA_ONEDNN_BRGEMM)
113126
message(STATUS "OneDNN BRGeMM micro-kernel support enabled")
114127
endif()
115128

129+
# OneDNN matmul primitive support via the threadpool runtime (optional, x86-64).
130+
# Same oneDNN source as the BRGeMM backend, but built with the THREADPOOL CPU
131+
# runtime instead of SEQ so oneDNN can call back into gemma.cpp's thread pool.
132+
if(GEMMA_ONEDNN_MATMUL)
133+
set(DNNL_BUILD_TESTS OFF CACHE BOOL "" FORCE)
134+
set(DNNL_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
135+
set(DNNL_CPU_RUNTIME "THREADPOOL" CACHE STRING "" FORCE)
136+
set(DNNL_GPU_RUNTIME "NONE" CACHE STRING "" FORCE)
137+
set(DNNL_LIBRARY_TYPE "STATIC" CACHE STRING "" FORCE)
138+
FetchContent_Declare(onednn
139+
GIT_REPOSITORY https://github.com/uxlfoundation/oneDNN.git
140+
GIT_TAG v3.11
141+
EXCLUDE_FROM_ALL
142+
)
143+
FetchContent_MakeAvailable(onednn)
144+
message(STATUS "OneDNN matmul primitive (threadpool runtime) support enabled")
145+
endif()
146+
116147
# Base source files
117148
set(SOURCES
118149
compression/compress-inl.h
@@ -185,6 +216,8 @@ set(SOURCES
185216
ops/matmul.h
186217
ops/brgemm.h
187218
ops/brgemm-inl.h
219+
ops/onednn_matmul.h
220+
ops/onednn_matmul-inl.h
188221
ops/ops-inl.h
189222
ops/ops.h
190223
ops/sum-inl.h
@@ -247,6 +280,10 @@ if(GEMMA_ONEDNN_BRGEMM)
247280
target_compile_definitions(libgemma PUBLIC GEMMA_ONEDNN_BRGEMM=1 DNNL_EXPERIMENTAL_UKERNEL)
248281
target_link_libraries(libgemma dnnl)
249282
endif()
283+
if(GEMMA_ONEDNN_MATMUL)
284+
target_compile_definitions(libgemma PUBLIC GEMMA_ONEDNN_MATMUL=1)
285+
target_link_libraries(libgemma dnnl)
286+
endif()
250287
install(TARGETS libgemma DESTINATION lib)
251288

252289
# Shared library target for C# interop
@@ -275,6 +312,10 @@ if(GEMMA_ONEDNN_BRGEMM)
275312
target_compile_definitions(gemma_shared PUBLIC GEMMA_ONEDNN_BRGEMM=1 DNNL_EXPERIMENTAL_UKERNEL)
276313
target_link_libraries(gemma_shared PRIVATE dnnl)
277314
endif()
315+
if(GEMMA_ONEDNN_MATMUL)
316+
target_compile_definitions(gemma_shared PUBLIC GEMMA_ONEDNN_MATMUL=1)
317+
target_link_libraries(gemma_shared PRIVATE dnnl)
318+
endif()
278319
install(TARGETS gemma_shared DESTINATION lib)
279320
install(FILES gemma/c_api.h DESTINATION include/gemma)
280321
install(FILES gemma/GemmaInterop.cs DESTINATION include/gemma)

‎MODULE.bazel‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ http_archive(
3636
],
3737
)
3838

39+
# Same oneDNN v3.11 source as @onednn, but built for the THREADPOOL CPU runtime
40+
# (the matmul-primitive backend, GEMMA_ONEDNN_MATMUL) rather than SEQ (BRGeMM).
41+
# oneDNN's CPU runtime is a whole-library compile-time choice, so the two cannot
42+
# share one build; this is a separate repo with a different build_file. The
43+
# tarball and sha256 are identical, so Bazel's download cache is shared and only
44+
# the arm selected by //:gemma_onednn_matmul actually compiles.
45+
http_archive(
46+
name = "onednn_tp",
47+
build_file = "@//bazel:onednn_threadpool.BUILD",
48+
sha256 = "04df98b18300daf6c3aa7cc2d5e7ce8a8f430fed1787151daed0254d8dd4e64e",
49+
strip_prefix = "oneDNN-3.11",
50+
urls = [
51+
"https://github.com/uxlfoundation/oneDNN/archive/refs/tags/v3.11.tar.gz",
52+
],
53+
)
54+
3955
http_archive(
4056
name = "com_google_absl_py",
4157
sha256 = "8a3d0830e4eb4f66c4fa907c06edf6ce1c719ced811a12e26d9d3162f8471758",

0 commit comments

Comments
 (0)