Skip to content

Commit 1fc313d

Browse files
CC-YehAwni Hannun
andauthored
Metal logging (#2904)
Co-authored-by: Awni Hannun <awni@apple.com>
1 parent f06a45f commit 1fc313d

9 files changed

Lines changed: 86 additions & 2 deletions

File tree

docs/src/dev/metal_logging.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Metal Logging
2+
=============
3+
4+
In debug builds, MLX compiles Metal kernels with ``os_log`` enabled so shader
5+
warnings and debug messages are visible during development.
6+
7+
.. note::
8+
Metal logging is only available with Metal 3.2 or higher (macOS 15 and up,
9+
iOS 18 and up).
10+
11+
To enable logging from kernels, first make sure to build in debug mode:
12+
13+
.. code-block:: bash
14+
15+
DEBUG=1 python -m pip install -e .
16+
17+
Then, in the kernel source code include MLX's logging shim and use
18+
``mlx::os_log``:
19+
20+
.. code-block::
21+
22+
#include "mlx/backend/metal/kernels/logging.h"
23+
24+
constant mlx::os_log logger("mlx", "my_kernel");
25+
26+
kernel void my_kernel(/* ... */) {
27+
// ...
28+
logger.log_debug("unexpected state: idx=%u", idx);
29+
}
30+
31+
When you run the program, set the Metal log level to your desired level and
32+
forward logs to ``stderr``:
33+
34+
.. code-block:: bash
35+
36+
MTL_LOG_LEVEL=MTLLogLevelDebug MTL_LOG_TO_STDERR=1 python script.py
37+
38+
See the `Metal logging guide`_ for more details.
39+
40+
.. _`Metal logging guide`: https://developer.apple.com/documentation/metal/logging-shader-debug-messages

docs/src/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,6 @@ are the CPU and GPU.
8989

9090
dev/extensions
9191
dev/metal_debugger
92+
dev/metal_logging
9293
dev/custom_metal_kernels
9394
dev/mlx_in_cpp

mlx/backend/metal/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function(make_jit_source SRC_FILE)
2222
endfunction(make_jit_source)
2323

2424
make_jit_source(utils kernels/bf16.h kernels/bf16_math.h kernels/complex.h
25-
kernels/defines.h)
25+
kernels/defines.h kernels/logging.h)
2626
make_jit_source(unary_ops kernels/erf.h kernels/expm1f.h kernels/fp8.h)
2727
make_jit_source(binary_ops)
2828
make_jit_source(ternary_ops)

mlx/backend/metal/device.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ MTL::Library* load_library(
224224
std::ostringstream msg;
225225
msg << "Failed to load the metallib " << lib_name << ".metallib. "
226226
<< "We attempted to load it from <" << current_binary_dir() << "/"
227-
<< lib_name << ".metallib" << ">";
227+
<< lib_name << ".metallib>";
228228
#ifdef SWIFTPM_BUNDLE
229229
msg << " and from the Swift PM bundle.";
230230
#endif
@@ -529,6 +529,11 @@ MTL::Library* Device::build_library_(const std::string& source_string) {
529529
auto options = MTL::CompileOptions::alloc()->init();
530530
options->setFastMathEnabled(false);
531531
options->setLanguageVersion(get_metal_version());
532+
#ifndef NDEBUG
533+
if (options->languageVersion() >= MTL::LanguageVersion3_2) {
534+
options->setEnableLogging(true);
535+
}
536+
#endif
532537
auto mtl_lib = device_->newLibrary(ns_code, options, &error);
533538
options->release();
534539

mlx/backend/metal/kernels/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(BASE_HEADERS
66
erf.h
77
expm1f.h
88
fp8.h
9+
logging.h
910
utils.h)
1011

1112
function(build_kernel_base TARGET SRCFILE DEPS)
@@ -20,6 +21,9 @@ function(build_kernel_base TARGET SRCFILE DEPS)
2021
if(MLX_METAL_DEBUG)
2122
set(METAL_FLAGS ${METAL_FLAGS} -gline-tables-only -frecord-sources)
2223
endif()
24+
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND MLX_METAL_VERSION GREATER_EQUAL 320)
25+
set(METAL_FLAGS ${METAL_FLAGS} -fmetal-enable-logging)
26+
endif()
2327
if(NOT CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "")
2428
set(METAL_FLAGS ${METAL_FLAGS}
2529
"-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")

mlx/backend/metal/kernels/binary_ops.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <metal_integer>
66
#include <metal_math>
77

8+
constant mlx::os_log logger("mlx", "binary_ops");
9+
810
struct Add {
911
template <typename T>
1012
T operator()(T x, T y) {
@@ -225,6 +227,8 @@ struct Power {
225227
T res = 1;
226228
// Undefined to raise integer to negative power
227229
if (exp < 0) {
230+
logger.log_debug(
231+
"int pow exp<0 (base=%ld exp=%ld)", (long)base, (long)exp);
228232
return 0;
229233
}
230234

mlx/backend/metal/kernels/indexing/masked_scatter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#pragma once
44

5+
constant mlx::os_log logger("mlx", "masked_assign");
6+
57
template <typename T, bool src_contiguous>
68
[[kernel]] void masked_assign_impl(
79
const device bool* mask [[buffer(0)]],
@@ -21,6 +23,7 @@ template <typename T, bool src_contiguous>
2123

2224
const uint src_index = scatter_offsets[idx];
2325
if (src_index >= src_batch_size) {
26+
logger.log_debug("Out of bound read from src");
2427
return;
2528
}
2629

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright © 2025 Apple Inc.
2+
3+
#pragma once
4+
5+
#if defined(__METAL_VERSION__) && (__METAL_VERSION__ >= 320)
6+
#include <metal_logging>
7+
8+
namespace mlx {
9+
using os_log = metal::os_log;
10+
} // namespace mlx
11+
12+
#else
13+
14+
namespace mlx {
15+
struct os_log {
16+
constexpr os_log(constant char*, constant char*) constant {}
17+
18+
template <typename... Args>
19+
void log_debug(constant char*, Args...) const {}
20+
21+
template <typename... Args>
22+
void log_debug(constant char*, Args...) const constant {}
23+
};
24+
} // namespace mlx
25+
26+
#endif

mlx/backend/metal/kernels/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "mlx/backend/metal/kernels/bf16_math.h"
99
#include "mlx/backend/metal/kernels/complex.h"
1010
#include "mlx/backend/metal/kernels/defines.h"
11+
#include "mlx/backend/metal/kernels/logging.h"
1112

1213
typedef half float16_t;
1314

0 commit comments

Comments
 (0)