ajh-code commited on
Commit
2b433c5
·
verified ·
1 Parent(s): 156e6c2

Add runtime/fused_gelu_up_runtime.py

Browse files
Files changed (1) hide show
  1. runtime/fused_gelu_up_runtime.py +236 -0
runtime/fused_gelu_up_runtime.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Experimental Python bridge for the side-by-side fused NVFP4 GELU-up ABI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ctypes
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+
10
+ class FusedGeluUpLibrary:
11
+ def __init__(self, library_path: Path, torch: Any):
12
+ self.torch = torch
13
+ self._enabled = True
14
+ self._closed = False
15
+ self._installed_modules: tuple[str, ...] = ()
16
+ self.library_path = library_path.resolve()
17
+ self.library = ctypes.CDLL(
18
+ str(self.library_path),
19
+ mode=ctypes.RTLD_LOCAL,
20
+ )
21
+ self.library.mage_nvfp4_last_error.argtypes = []
22
+ self.library.mage_nvfp4_last_error.restype = ctypes.c_char_p
23
+ self.library.mage_nvfp4_create_context.argtypes = [
24
+ ctypes.c_int,
25
+ ctypes.POINTER(ctypes.c_void_p),
26
+ ]
27
+ self.library.mage_nvfp4_create_context.restype = ctypes.c_int
28
+ self.library.mage_nvfp4_destroy_context.argtypes = [ctypes.c_void_p]
29
+ self.library.mage_nvfp4_destroy_context.restype = ctypes.c_int
30
+ self.forward_function = self.library.mage_nvfp4_gelu_up_forward
31
+ self.forward_function.argtypes = [
32
+ ctypes.c_void_p,
33
+ ctypes.c_void_p,
34
+ ctypes.c_void_p,
35
+ ctypes.c_size_t,
36
+ ctypes.c_void_p,
37
+ ctypes.c_size_t,
38
+ ctypes.c_void_p,
39
+ ctypes.c_void_p,
40
+ ctypes.c_void_p,
41
+ ctypes.c_int,
42
+ ctypes.c_int,
43
+ ctypes.c_int,
44
+ ctypes.c_size_t,
45
+ ]
46
+ self.forward_function.restype = ctypes.c_int
47
+ context = ctypes.c_void_p()
48
+ status = self.library.mage_nvfp4_create_context(
49
+ torch.cuda.current_device(),
50
+ ctypes.byref(context),
51
+ )
52
+ if status:
53
+ raise RuntimeError(self.last_error("creating fused GELU-up context"))
54
+ self.context = context
55
+
56
+ @property
57
+ def enabled(self) -> bool:
58
+ return self._enabled and not self._closed and bool(self.context)
59
+
60
+ @property
61
+ def installed_modules(self) -> tuple[str, ...]:
62
+ return self._installed_modules
63
+
64
+ def set_enabled(self, enabled: bool) -> None:
65
+ if enabled and self._closed:
66
+ raise RuntimeError("fused GELU-up runtime is closed")
67
+ self._enabled = bool(enabled)
68
+
69
+ def set_installed_modules(self, modules: list[str]) -> None:
70
+ self._installed_modules = tuple(modules)
71
+
72
+ def last_error(self, operation: str) -> str:
73
+ raw = self.library.mage_nvfp4_last_error()
74
+ message = raw.decode("utf-8", errors="replace") if raw else "unknown error"
75
+ return f"{operation}: {message}"
76
+
77
+ def forward(self, value: Any, projection: Any) -> Any:
78
+ if not self.enabled:
79
+ raise RuntimeError("fused GELU-up runtime is unavailable")
80
+ torch = self.torch
81
+ flattened = value.reshape(-1, projection.in_features).contiguous()
82
+ logical_m = int(flattened.shape[0])
83
+ padded_m = ((logical_m + 7) // 8) * 8
84
+ output = torch.empty(
85
+ (padded_m, projection.out_features),
86
+ dtype=torch.bfloat16,
87
+ device=flattened.device,
88
+ )
89
+ status = self.forward_function(
90
+ self.context,
91
+ ctypes.c_void_p(flattened.data_ptr()),
92
+ ctypes.c_void_p(projection.packed_weight.data_ptr()),
93
+ projection.packed_weight.numel(),
94
+ ctypes.c_void_p(projection.weight_scales.data_ptr()),
95
+ projection.weight_scales.numel(),
96
+ ctypes.c_void_p(projection.weight_scale.data_ptr()),
97
+ ctypes.c_void_p(projection.bias.data_ptr()),
98
+ ctypes.c_void_p(output.data_ptr()),
99
+ logical_m,
100
+ projection.in_features,
101
+ projection.out_features,
102
+ int(torch.cuda.current_stream().cuda_stream),
103
+ )
104
+ if status:
105
+ raise RuntimeError(self.last_error("running fused GELU-up"))
106
+ return output.narrow(0, 0, logical_m).view(
107
+ (*value.shape[:-1], projection.out_features)
108
+ )
109
+
110
+ def close(self) -> None:
111
+ self._enabled = False
112
+ self._closed = True
113
+ if self.context:
114
+ status = self.library.mage_nvfp4_destroy_context(self.context)
115
+ self.context = ctypes.c_void_p()
116
+ if status:
117
+ raise RuntimeError(
118
+ self.last_error("destroying fused GELU-up context")
119
+ )
120
+
121
+
122
+ def install_fused_gelu_up(
123
+ transformer: Any,
124
+ *,
125
+ library_path: Path,
126
+ torch: Any,
127
+ stream_names: tuple[str, ...] = ("img_mlp", "txt_mlp"),
128
+ ) -> tuple[FusedGeluUpLibrary, dict[str, Any]]:
129
+ """Replace all Mage GELU-up modules while preserving packed parameters."""
130
+
131
+ allowed_streams = ("img_mlp", "txt_mlp")
132
+ requested_streams = tuple(dict.fromkeys(stream_names))
133
+ if not requested_streams or any(
134
+ name not in allowed_streams for name in requested_streams
135
+ ):
136
+ raise RuntimeError(
137
+ "fused GELU-up streams must be a non-empty subset of "
138
+ "('img_mlp', 'txt_mlp')"
139
+ )
140
+ runtime = FusedGeluUpLibrary(library_path, torch)
141
+
142
+ class FusedGeluUp(torch.nn.Module):
143
+ is_mage_fused_gelu_up_wrapper = True
144
+ _xpo3_fused_gelu_up = True
145
+
146
+ def __init__(self, activation: Any):
147
+ super().__init__()
148
+ self.original_activation = activation
149
+
150
+ @property
151
+ def proj(self) -> Any:
152
+ return self.original_activation.proj
153
+
154
+ @property
155
+ def projection(self) -> Any:
156
+ return self.original_activation.proj
157
+
158
+ def forward(self, hidden_states: Any) -> Any:
159
+ if runtime.enabled:
160
+ return runtime.forward(hidden_states, self.projection)
161
+ return self.original_activation(hidden_states)
162
+
163
+ installed: list[str] = []
164
+ skipped_bf16: list[str] = []
165
+ skipped_replaced: list[str] = []
166
+ try:
167
+ for block_index, block in enumerate(transformer.transformer_blocks):
168
+ for stream_name in requested_streams:
169
+ feed_forward = getattr(block, stream_name)
170
+ if not hasattr(feed_forward, "net"):
171
+ if stream_name == "img_mlp":
172
+ skipped_replaced.append(
173
+ f"transformer_blocks.{block_index}.{stream_name}"
174
+ )
175
+ continue
176
+ raise RuntimeError(
177
+ f"missing GELU net at block {block_index} {stream_name}"
178
+ )
179
+ activation = feed_forward.net[0]
180
+ if getattr(activation, "approximate", None) != "tanh":
181
+ raise RuntimeError(
182
+ f"expected tanh GELU at block {block_index} {stream_name}"
183
+ )
184
+ projection = getattr(activation, "proj", None)
185
+ required = (
186
+ "packed_weight",
187
+ "weight_scales",
188
+ "weight_scale",
189
+ "bias",
190
+ "in_features",
191
+ "out_features",
192
+ )
193
+ if projection is None:
194
+ raise RuntimeError(
195
+ f"missing GELU projection at block {block_index} "
196
+ f"{stream_name}"
197
+ )
198
+ if any(
199
+ not hasattr(projection, name) for name in required
200
+ ):
201
+ skipped_bf16.append(
202
+ f"transformer_blocks.{block_index}."
203
+ f"{stream_name}.net.0"
204
+ )
205
+ continue
206
+ if (
207
+ int(projection.in_features) != 3072
208
+ or int(projection.out_features) != 12288
209
+ ):
210
+ raise RuntimeError(
211
+ "unexpected Mage GELU-up dimensions at "
212
+ f"block {block_index} {stream_name}"
213
+ )
214
+ module_name = (
215
+ f"transformer_blocks.{block_index}.{stream_name}.net.0"
216
+ )
217
+ feed_forward.net[0] = FusedGeluUp(activation)
218
+ installed.append(module_name)
219
+ except Exception:
220
+ runtime.close()
221
+ raise
222
+
223
+ runtime.set_installed_modules(installed)
224
+ return runtime, {
225
+ "mode": "nvfp4_gelu_up",
226
+ "library_path": str(library_path.resolve()),
227
+ "enabled": runtime.enabled,
228
+ "stream_names": list(requested_streams),
229
+ "module_count": len(installed),
230
+ "modules": installed,
231
+ "installed_modules": installed,
232
+ "skipped_bf16_count": len(skipped_bf16),
233
+ "skipped_bf16_modules": skipped_bf16,
234
+ "skipped_replaced_count": len(skipped_replaced),
235
+ "skipped_replaced_modules": skipped_replaced,
236
+ }