tensorflow-metal-plugin 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/Makefile +28 -3
- {tensorflow_metal_plugin-0.1.2/tensorflow_metal_plugin.egg-info → tensorflow_metal_plugin-0.2.0}/PKG-INFO +40 -21
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/README.md +39 -20
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/setup.py +1 -1
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/plugin_init.cc +26 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_cudnn_rnn_ops.mm +321 -62
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_gather_scatter_ops.mm +127 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_kernel_util.mm +10 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_matmul_op.mm +93 -7
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_maxpool_argmax_ops.mm +99 -35
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_misc_ops.mm +142 -8
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_mps_graph.mm +12 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_random_ops.mm +34 -24
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_shader_library.h +9 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_shader_library.mm +275 -140
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_training_ops.mm +57 -42
- tensorflow_metal_plugin-0.2.0/src/tensorflow/core/common_runtime/metal/metal_graph.h +43 -0
- tensorflow_metal_plugin-0.2.0/src/tensorflow/core/common_runtime/metal/metal_graph.mm +570 -0
- tensorflow_metal_plugin-0.2.0/src/tensorflow/core/common_runtime/metal/metal_profiler.h +58 -0
- tensorflow_metal_plugin-0.2.0/src/tensorflow/core/common_runtime/metal/metal_profiler.mm +310 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_stream.h +11 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_stream.mm +24 -1
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_stream_executor.mm +120 -12
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0/tensorflow_metal_plugin.egg-info}/PKG-INFO +40 -21
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tensorflow_metal_plugin.egg-info/SOURCES.txt +4 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/LICENSE +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/MANIFEST.in +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/pyproject.toml +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/setup.cfg +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_activation_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_alias_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_array_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_batch_norm_global_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_batch_norm_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_batch_space_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_bincount_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_box_proposal_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_collective_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_compare_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_conv3d_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_conv_generic_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_conv_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_crop_resize_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_ctc_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_debug_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_depthwise_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_dilation_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_dynamic_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_elementwise_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_extra_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_fft_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_fill_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_fused_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_identity_op.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_image2_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_image_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_index_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_inplace_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_kernel_util.h +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_kernels.h +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_kernels.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_linalg_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_matrix_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_misc2_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_mps_graph.h +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_nms_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_nn_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_pool_variant_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_pooling_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_quant_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_quantize_dequantize_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_random_dist_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_reduction_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_ref_variable_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_resize_grad_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_rnn_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_search_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_slice_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_sparse_manip_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_sparse_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_sparse_segment_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_strided_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_transform_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/kernels/metal_volume_patch_ops.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_buffer_registry.h +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_buffer_registry.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_platform.h +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_platform.mm +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/src/tensorflow/core/common_runtime/metal/metal_stream_executor.h +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tensorflow-plugins/__init__.py +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tensorflow_metal_plugin.egg-info/dependency_links.txt +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tensorflow_metal_plugin.egg-info/requires.txt +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tensorflow_metal_plugin.egg-info/top_level.txt +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tools/check_symbols.sh +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tools/compile_shaders.py +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tools/op_sweep.py +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tools/probe_stream_options.sh +0 -0
- {tensorflow_metal_plugin-0.1.2 → tensorflow_metal_plugin-0.2.0}/tools/recipes.py +0 -0
|
@@ -23,6 +23,19 @@ SDK := $(shell xcrun --sdk macosx --show-sdk-path 2>/dev/null)
|
|
|
23
23
|
BUILD := build
|
|
24
24
|
OUT := $(BUILD)/libmetal_plugin.dylib
|
|
25
25
|
|
|
26
|
+
# Which TensorFlow the objects in $(BUILD) were compiled against.
|
|
27
|
+
#
|
|
28
|
+
# The header dependencies recorded by -MMD name paths inside that TensorFlow,
|
|
29
|
+
# and those paths keep existing when PYTHON is pointed at a different one, so
|
|
30
|
+
# make sees nothing to redo and links objects built against two different
|
|
31
|
+
# TensorFlows. The result is a library that fails to load with an absl symbol
|
|
32
|
+
# missing, which says nothing about the cause. This makes the include path
|
|
33
|
+
# itself a dependency.
|
|
34
|
+
STAMP := $(BUILD)/tf-include-path
|
|
35
|
+
$(shell mkdir -p $(BUILD); \
|
|
36
|
+
[ "$$(cat $(STAMP) 2>/dev/null)" = "$(TF_INCLUDE)" ] || \
|
|
37
|
+
printf '%s' "$(TF_INCLUDE)" > $(STAMP))
|
|
38
|
+
|
|
26
39
|
SOURCES := src/plugin_init.cc \
|
|
27
40
|
$(wildcard src/tensorflow/core/common_runtime/metal/*.mm) \
|
|
28
41
|
$(wildcard src/tensorflow/core/common_runtime/metal/kernels/*.mm)
|
|
@@ -69,7 +82,7 @@ LDFLAGS := -dynamiclib $(FRAMEWORKS) \
|
|
|
69
82
|
-Wl,-undefined,dynamic_lookup \
|
|
70
83
|
-Wl,-rpath,$(TF_LIB)
|
|
71
84
|
|
|
72
|
-
.PHONY: all clean test sweep install
|
|
85
|
+
.PHONY: all clean test test-stream sweep install
|
|
73
86
|
|
|
74
87
|
all: $(OUT)
|
|
75
88
|
|
|
@@ -78,7 +91,7 @@ $(OUT): $(OBJECTS)
|
|
|
78
91
|
$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
|
|
79
92
|
@echo "built $@"
|
|
80
93
|
|
|
81
|
-
$(BUILD)/%.o: src/%
|
|
94
|
+
$(BUILD)/%.o: src/% $(STAMP)
|
|
82
95
|
@mkdir -p $(dir $@)
|
|
83
96
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
|
84
97
|
|
|
@@ -86,9 +99,21 @@ $(BUILD)/%.o: src/%
|
|
|
86
99
|
check-symbols: $(OUT)
|
|
87
100
|
@bash tools/check_symbols.sh $(OUT)
|
|
88
101
|
|
|
89
|
-
test: $(OUT)
|
|
102
|
+
test: $(OUT) test-stream
|
|
90
103
|
$(PYTHON) tests/run_tests.py
|
|
91
104
|
|
|
105
|
+
# The StreamExecutor C API driven directly, without TensorFlow. Reaches what
|
|
106
|
+
# no op can: memset32 with a pattern that is not four equal bytes has one
|
|
107
|
+
# caller in the whole tree and it is a CUDA-only kernel.
|
|
108
|
+
$(BUILD)/stream_executor_test: tests/stream_executor_test.mm $(OUT)
|
|
109
|
+
@mkdir -p $(dir $@)
|
|
110
|
+
$(CXX) $(CXXFLAGS) tests/stream_executor_test.mm -o $@ \
|
|
111
|
+
-framework Foundation -L$(TF_LIB) -ltensorflow_framework.2 \
|
|
112
|
+
-Wl,-rpath,$(TF_LIB)
|
|
113
|
+
|
|
114
|
+
test-stream: $(BUILD)/stream_executor_test
|
|
115
|
+
$(BUILD)/stream_executor_test $(OUT)
|
|
116
|
+
|
|
92
117
|
# Every registered op, through TensorFlow's own dispatch, against the CPU.
|
|
93
118
|
sweep: $(OUT)
|
|
94
119
|
PYTHONPATH=tools $(PYTHON) tools/op_sweep.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tensorflow-metal-plugin
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Metal GPU backend for TensorFlow on Apple silicon
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -28,10 +28,15 @@ PluggableDevice. It loads into a stock TensorFlow wheel and adds
|
|
|
28
28
|
`/physical_device:GPU:0`.
|
|
29
29
|
|
|
30
30
|
This is the out-of-tree form of the backend proposed in
|
|
31
|
-
[tensorflow/tensorflow#
|
|
31
|
+
[tensorflow/tensorflow#126384](https://github.com/tensorflow/tensorflow/pull/126384).
|
|
32
32
|
The sources are the same; the only difference is this repository exports
|
|
33
|
-
`SE_InitPlugin` and `
|
|
34
|
-
form hands the same function pointers to
|
|
33
|
+
`SE_InitPlugin`, `TF_InitKernel`, `TF_InitProfiler` and `TF_InitGraph` from a
|
|
34
|
+
shared object, where the in-tree form hands the same function pointers to
|
|
35
|
+
`RegisterPluggableDevicePlugin`.
|
|
36
|
+
|
|
37
|
+
Four modules, then: the device and its memory, the kernels, a profiler that
|
|
38
|
+
puts Metal work on the TensorFlow timeline, and a graph pass that fuses a bias
|
|
39
|
+
and an activation into the convolution or matrix multiply in front of them.
|
|
35
40
|
|
|
36
41
|
## Status
|
|
37
42
|
|
|
@@ -126,8 +131,15 @@ error raised. `model.fit` reported `[nan, nan, nan]` and carried on.
|
|
|
126
131
|
|
|
127
132
|
While those entry points are missing, every Metal kernel waits for the GPU
|
|
128
133
|
before returning, which closes the window. It is announced in a warning at
|
|
129
|
-
load, and `TF_METAL_SYNCHRONOUS` forces it either way.
|
|
130
|
-
|
|
134
|
+
load, and `TF_METAL_SYNCHRONOUS` forces it either way.
|
|
135
|
+
|
|
136
|
+
Where the entry points do exist, the plugin implements `AssignVariableOp`,
|
|
137
|
+
`AssignAddVariableOp` and `AssignSubVariableOp` itself, on the device, and
|
|
138
|
+
nothing touches a variable from the host at all. That is what makes running
|
|
139
|
+
asynchronously safe rather than merely faster: without those kernels, an
|
|
140
|
+
asynchronous run reproduced the same `nan` on TensorFlow 2.19.1, where the C
|
|
141
|
+
API is present. With them, a training step is 11.48 ms against 21.04 ms on the
|
|
142
|
+
CPU, and correct.
|
|
131
143
|
|
|
132
144
|
## Is it faster than the CPU
|
|
133
145
|
|
|
@@ -136,21 +148,25 @@ on an M4 Max against TensorFlow 2.21.0, median of ten runs each, both devices
|
|
|
136
148
|
in the same process on the same data, waiting for the device before stopping
|
|
137
149
|
the clock:
|
|
138
150
|
|
|
139
|
-
Two columns
|
|
140
|
-
|
|
141
|
-
|
|
151
|
+
Two columns, because the wait above costs most of it. "Today" is a released
|
|
152
|
+
TensorFlow, 2.21.0, where the kernel C API for resource variables is missing
|
|
153
|
+
and every kernel therefore waits. "Async" is 2.19.1, which still exports that
|
|
154
|
+
API, so the same code runs asynchronously; it is what a released TensorFlow
|
|
155
|
+
does again once
|
|
142
156
|
[#126374](https://github.com/tensorflow/tensorflow/issues/126374) is fixed.
|
|
157
|
+
Both columns are measured, not projected.
|
|
143
158
|
|
|
144
159
|
| | GPU today | CPU | today | async |
|
|
145
160
|
| --- | ---: | ---: | ---: | ---: |
|
|
146
|
-
| MatMul 2048x2048 |
|
|
147
|
-
| Conv2D, batch 64, 64x64x32 to 64 |
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
|
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
|
|
|
161
|
+
| MatMul 2048x2048 | 1.78 ms | 11.97 ms | **6.7x** | 5.5x |
|
|
162
|
+
| Conv2D, batch 64, 64x64x32 to 64 | 2.25 ms | 8.95 ms | **4.0x** | 4.2x |
|
|
163
|
+
| CNN training step, SGD, batch 128 | 12.60 ms | 18.80 ms | 1.5x | 1.8x |
|
|
164
|
+
| MatMul 1024x1024 | 1.19 ms | 1.89 ms | 1.6x | 2.0x |
|
|
165
|
+
| Conv2D, batch 16 | 1.37 ms | 2.31 ms | 1.7x | 1.7x |
|
|
166
|
+
| CNN forward, batch 128 | 4.55 ms | 5.17 ms | 1.1x | 1.5x |
|
|
167
|
+
| MatMul 512x512 | 0.37 ms | 0.34 ms | 0.9x | 1.0x |
|
|
168
|
+
| ReduceSum 4096x4096 | 0.46 ms | 0.28 ms | 0.6x | 0.7x |
|
|
169
|
+
| Elementwise 4096x4096 | 3.05 ms | 1.36 ms | 0.5x | 0.5x |
|
|
154
170
|
|
|
155
171
|
The pattern is the ordinary one and worth stating plainly: the GPU wins where
|
|
156
172
|
there is arithmetic to do per byte moved, and loses where there is not. A
|
|
@@ -159,9 +175,12 @@ operations per element, so it is bound by memory on a machine whose CPU shares
|
|
|
159
175
|
that same memory. Small matrices lose to the cost of getting work to the
|
|
160
176
|
device at all.
|
|
161
177
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
178
|
+
The convolution numbers owe as much to the graph pass as to the kernels. It
|
|
179
|
+
folds the bias and the activation into the convolution, and it turns
|
|
180
|
+
TensorFlow's layout optimizer off, which was inserting an NHWC to NCHW
|
|
181
|
+
transpose on either side of every convolution: on a 4x16x16x8 case those cost
|
|
182
|
+
42.8 and 44.2 microseconds around a 43.0 microsecond convolution. MPSGraph
|
|
183
|
+
takes either layout, so the rewrite was pure loss.
|
|
165
184
|
|
|
166
185
|
`benchmarks/benchmark.py` reproduces the table.
|
|
167
186
|
|
|
@@ -264,7 +283,7 @@ Metal kernels with their dtypes is in
|
|
|
264
283
|
## Layout
|
|
265
284
|
|
|
266
285
|
```
|
|
267
|
-
src/plugin_init.cc the
|
|
286
|
+
src/plugin_init.cc the exported entry points
|
|
268
287
|
src/tensorflow/core/common_runtime/metal/ the backend, verbatim from the
|
|
269
288
|
TensorFlow tree
|
|
270
289
|
tools/ build probes and the symbol check
|
|
@@ -5,10 +5,15 @@ PluggableDevice. It loads into a stock TensorFlow wheel and adds
|
|
|
5
5
|
`/physical_device:GPU:0`.
|
|
6
6
|
|
|
7
7
|
This is the out-of-tree form of the backend proposed in
|
|
8
|
-
[tensorflow/tensorflow#
|
|
8
|
+
[tensorflow/tensorflow#126384](https://github.com/tensorflow/tensorflow/pull/126384).
|
|
9
9
|
The sources are the same; the only difference is this repository exports
|
|
10
|
-
`SE_InitPlugin` and `
|
|
11
|
-
form hands the same function pointers to
|
|
10
|
+
`SE_InitPlugin`, `TF_InitKernel`, `TF_InitProfiler` and `TF_InitGraph` from a
|
|
11
|
+
shared object, where the in-tree form hands the same function pointers to
|
|
12
|
+
`RegisterPluggableDevicePlugin`.
|
|
13
|
+
|
|
14
|
+
Four modules, then: the device and its memory, the kernels, a profiler that
|
|
15
|
+
puts Metal work on the TensorFlow timeline, and a graph pass that fuses a bias
|
|
16
|
+
and an activation into the convolution or matrix multiply in front of them.
|
|
12
17
|
|
|
13
18
|
## Status
|
|
14
19
|
|
|
@@ -103,8 +108,15 @@ error raised. `model.fit` reported `[nan, nan, nan]` and carried on.
|
|
|
103
108
|
|
|
104
109
|
While those entry points are missing, every Metal kernel waits for the GPU
|
|
105
110
|
before returning, which closes the window. It is announced in a warning at
|
|
106
|
-
load, and `TF_METAL_SYNCHRONOUS` forces it either way.
|
|
107
|
-
|
|
111
|
+
load, and `TF_METAL_SYNCHRONOUS` forces it either way.
|
|
112
|
+
|
|
113
|
+
Where the entry points do exist, the plugin implements `AssignVariableOp`,
|
|
114
|
+
`AssignAddVariableOp` and `AssignSubVariableOp` itself, on the device, and
|
|
115
|
+
nothing touches a variable from the host at all. That is what makes running
|
|
116
|
+
asynchronously safe rather than merely faster: without those kernels, an
|
|
117
|
+
asynchronous run reproduced the same `nan` on TensorFlow 2.19.1, where the C
|
|
118
|
+
API is present. With them, a training step is 11.48 ms against 21.04 ms on the
|
|
119
|
+
CPU, and correct.
|
|
108
120
|
|
|
109
121
|
## Is it faster than the CPU
|
|
110
122
|
|
|
@@ -113,21 +125,25 @@ on an M4 Max against TensorFlow 2.21.0, median of ten runs each, both devices
|
|
|
113
125
|
in the same process on the same data, waiting for the device before stopping
|
|
114
126
|
the clock:
|
|
115
127
|
|
|
116
|
-
Two columns
|
|
117
|
-
|
|
118
|
-
|
|
128
|
+
Two columns, because the wait above costs most of it. "Today" is a released
|
|
129
|
+
TensorFlow, 2.21.0, where the kernel C API for resource variables is missing
|
|
130
|
+
and every kernel therefore waits. "Async" is 2.19.1, which still exports that
|
|
131
|
+
API, so the same code runs asynchronously; it is what a released TensorFlow
|
|
132
|
+
does again once
|
|
119
133
|
[#126374](https://github.com/tensorflow/tensorflow/issues/126374) is fixed.
|
|
134
|
+
Both columns are measured, not projected.
|
|
120
135
|
|
|
121
136
|
| | GPU today | CPU | today | async |
|
|
122
137
|
| --- | ---: | ---: | ---: | ---: |
|
|
123
|
-
| MatMul 2048x2048 |
|
|
124
|
-
| Conv2D, batch 64, 64x64x32 to 64 |
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
|
130
|
-
|
|
|
138
|
+
| MatMul 2048x2048 | 1.78 ms | 11.97 ms | **6.7x** | 5.5x |
|
|
139
|
+
| Conv2D, batch 64, 64x64x32 to 64 | 2.25 ms | 8.95 ms | **4.0x** | 4.2x |
|
|
140
|
+
| CNN training step, SGD, batch 128 | 12.60 ms | 18.80 ms | 1.5x | 1.8x |
|
|
141
|
+
| MatMul 1024x1024 | 1.19 ms | 1.89 ms | 1.6x | 2.0x |
|
|
142
|
+
| Conv2D, batch 16 | 1.37 ms | 2.31 ms | 1.7x | 1.7x |
|
|
143
|
+
| CNN forward, batch 128 | 4.55 ms | 5.17 ms | 1.1x | 1.5x |
|
|
144
|
+
| MatMul 512x512 | 0.37 ms | 0.34 ms | 0.9x | 1.0x |
|
|
145
|
+
| ReduceSum 4096x4096 | 0.46 ms | 0.28 ms | 0.6x | 0.7x |
|
|
146
|
+
| Elementwise 4096x4096 | 3.05 ms | 1.36 ms | 0.5x | 0.5x |
|
|
131
147
|
|
|
132
148
|
The pattern is the ordinary one and worth stating plainly: the GPU wins where
|
|
133
149
|
there is arithmetic to do per byte moved, and loses where there is not. A
|
|
@@ -136,9 +152,12 @@ operations per element, so it is bound by memory on a machine whose CPU shares
|
|
|
136
152
|
that same memory. Small matrices lose to the cost of getting work to the
|
|
137
153
|
device at all.
|
|
138
154
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
155
|
+
The convolution numbers owe as much to the graph pass as to the kernels. It
|
|
156
|
+
folds the bias and the activation into the convolution, and it turns
|
|
157
|
+
TensorFlow's layout optimizer off, which was inserting an NHWC to NCHW
|
|
158
|
+
transpose on either side of every convolution: on a 4x16x16x8 case those cost
|
|
159
|
+
42.8 and 44.2 microseconds around a 43.0 microsecond convolution. MPSGraph
|
|
160
|
+
takes either layout, so the rewrite was pure loss.
|
|
142
161
|
|
|
143
162
|
`benchmarks/benchmark.py` reproduces the table.
|
|
144
163
|
|
|
@@ -241,7 +260,7 @@ Metal kernels with their dtypes is in
|
|
|
241
260
|
## Layout
|
|
242
261
|
|
|
243
262
|
```
|
|
244
|
-
src/plugin_init.cc the
|
|
263
|
+
src/plugin_init.cc the exported entry points
|
|
245
264
|
src/tensorflow/core/common_runtime/metal/ the backend, verbatim from the
|
|
246
265
|
TensorFlow tree
|
|
247
266
|
tools/ build probes and the symbol check
|
|
@@ -75,7 +75,7 @@ class BinaryDistribution(Distribution):
|
|
|
75
75
|
|
|
76
76
|
setup(
|
|
77
77
|
name="tensorflow-metal-plugin",
|
|
78
|
-
version="0.
|
|
78
|
+
version="0.2.0",
|
|
79
79
|
description="Metal GPU backend for TensorFlow on Apple silicon",
|
|
80
80
|
long_description=(HERE / "README.md").read_text(),
|
|
81
81
|
long_description_content_type="text/markdown",
|
|
@@ -27,7 +27,9 @@ limitations under the License.
|
|
|
27
27
|
#include "tensorflow/c/experimental/stream_executor/stream_executor.h"
|
|
28
28
|
#include "tensorflow/c/tf_status.h"
|
|
29
29
|
#include "tensorflow/core/common_runtime/metal/kernels/metal_kernels.h"
|
|
30
|
+
#include "tensorflow/core/common_runtime/metal/metal_graph.h"
|
|
30
31
|
#include "tensorflow/core/common_runtime/metal/metal_platform.h"
|
|
32
|
+
#include "tensorflow/core/common_runtime/metal/metal_profiler.h"
|
|
31
33
|
|
|
32
34
|
namespace {
|
|
33
35
|
|
|
@@ -55,4 +57,28 @@ void SE_InitPlugin(SE_PlatformRegistrationParams* params, TF_Status* status) {
|
|
|
55
57
|
|
|
56
58
|
void TF_InitKernel() { tensorflow::metal::RegisterAllMetalKernels(); }
|
|
57
59
|
|
|
60
|
+
// Optional: TensorFlow looks this up and carries on without it if absent. It
|
|
61
|
+
// is what puts a Metal row in the trace viewer next to the host's.
|
|
62
|
+
void TF_InitProfiler(TF_ProfilerRegistrationParams* params,
|
|
63
|
+
TF_Status* status) {
|
|
64
|
+
if (MetalDisabledByEnvironment()) {
|
|
65
|
+
TF_SetStatus(status, TF_FAILED_PRECONDITION,
|
|
66
|
+
"Metal: backend disabled by TF_DISABLE_METAL.");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
tensorflow::metal::MetalInitProfiler(params, status);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Optional, like the profiler. Fuses a bias and an activation into the
|
|
73
|
+
// convolution or matrix multiply in front of them, which this backend has
|
|
74
|
+
// kernels for and which nothing else produces for a pluggable device.
|
|
75
|
+
void TF_InitGraph(TP_OptimizerRegistrationParams* params, TF_Status* status) {
|
|
76
|
+
if (MetalDisabledByEnvironment()) {
|
|
77
|
+
TF_SetStatus(status, TF_FAILED_PRECONDITION,
|
|
78
|
+
"Metal: backend disabled by TF_DISABLE_METAL.");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
tensorflow::metal::MetalInitGraph(params, status);
|
|
82
|
+
}
|
|
83
|
+
|
|
58
84
|
} // extern "C"
|