bitsandbytes 0.50.0__py3-none-win_arm64.whl
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.
- bitsandbytes/__init__.py +78 -0
- bitsandbytes/__main__.py +4 -0
- bitsandbytes/_ops.py +510 -0
- bitsandbytes/autograd/__init__.py +0 -0
- bitsandbytes/autograd/_functions.py +491 -0
- bitsandbytes/backends/__init__.py +0 -0
- bitsandbytes/backends/cpu/__init__.py +0 -0
- bitsandbytes/backends/cpu/ops.py +580 -0
- bitsandbytes/backends/cuda/__init__.py +0 -0
- bitsandbytes/backends/cuda/ops.py +1199 -0
- bitsandbytes/backends/default/__init__.py +0 -0
- bitsandbytes/backends/default/ops.py +632 -0
- bitsandbytes/backends/hpu/__init__.py +0 -0
- bitsandbytes/backends/hpu/ops.py +53 -0
- bitsandbytes/backends/mps/__init__.py +0 -0
- bitsandbytes/backends/mps/ops.py +277 -0
- bitsandbytes/backends/triton/__init__.py +0 -0
- bitsandbytes/backends/triton/kernels_4bit.py +577 -0
- bitsandbytes/backends/triton/kernels_8bit_quant.py +195 -0
- bitsandbytes/backends/triton/kernels_optim.py +1177 -0
- bitsandbytes/backends/triton/ops.py +304 -0
- bitsandbytes/backends/utils.py +94 -0
- bitsandbytes/backends/xpu/__init__.py +0 -0
- bitsandbytes/backends/xpu/ops.py +305 -0
- bitsandbytes/cextension.py +405 -0
- bitsandbytes/consts.py +12 -0
- bitsandbytes/cuda_specs.py +111 -0
- bitsandbytes/diagnostics/__init__.py +0 -0
- bitsandbytes/diagnostics/cuda.py +193 -0
- bitsandbytes/diagnostics/main.py +134 -0
- bitsandbytes/diagnostics/utils.py +12 -0
- bitsandbytes/functional.py +1810 -0
- bitsandbytes/libbitsandbytes_cpu.dll +0 -0
- bitsandbytes/nn/__init__.py +19 -0
- bitsandbytes/nn/modules.py +1220 -0
- bitsandbytes/nn/parametrize.py +206 -0
- bitsandbytes/optim/__init__.py +22 -0
- bitsandbytes/optim/adagrad.py +187 -0
- bitsandbytes/optim/adam.py +346 -0
- bitsandbytes/optim/adamw.py +337 -0
- bitsandbytes/optim/ademamix.py +410 -0
- bitsandbytes/optim/lamb.py +190 -0
- bitsandbytes/optim/lars.py +259 -0
- bitsandbytes/optim/lion.py +266 -0
- bitsandbytes/optim/optimizer.py +756 -0
- bitsandbytes/optim/rmsprop.py +170 -0
- bitsandbytes/optim/sgd.py +152 -0
- bitsandbytes/py.typed +0 -0
- bitsandbytes/utils.py +208 -0
- bitsandbytes-0.50.0.dist-info/METADATA +288 -0
- bitsandbytes-0.50.0.dist-info/RECORD +54 -0
- bitsandbytes-0.50.0.dist-info/WHEEL +5 -0
- bitsandbytes-0.50.0.dist-info/licenses/LICENSE +21 -0
- bitsandbytes-0.50.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1177 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import torch
|
|
5
|
+
|
|
6
|
+
import triton
|
|
7
|
+
import triton.language as tl
|
|
8
|
+
|
|
9
|
+
# from triton.language.extra import libdevice
|
|
10
|
+
from .kernels_8bit_quant import (
|
|
11
|
+
dequant_8bit_blockwise,
|
|
12
|
+
dequant_8bit_blockwise_kernel_util,
|
|
13
|
+
quantize_8bit_blockwise_kernel_util,
|
|
14
|
+
quantize_blockwise_triton,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
MOMENTUM = 0
|
|
18
|
+
RMSPROP = 1
|
|
19
|
+
ADAGRAD = 2
|
|
20
|
+
ADAM = 3
|
|
21
|
+
# LION should be larger than MOMENTUM, RMSPROP, ADAGRAD due to comparison in kernels
|
|
22
|
+
LION = 4
|
|
23
|
+
ADEMAMIX = 5
|
|
24
|
+
|
|
25
|
+
name2optimizer_id = {
|
|
26
|
+
"momentum": MOMENTUM,
|
|
27
|
+
"lars": MOMENTUM,
|
|
28
|
+
"rmsprop": RMSPROP,
|
|
29
|
+
"adagrad": ADAGRAD,
|
|
30
|
+
"adam": ADAM,
|
|
31
|
+
"lamb": ADAM,
|
|
32
|
+
"lion": LION,
|
|
33
|
+
"ademamix": ADEMAMIX,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@triton.jit
|
|
38
|
+
def _optimizer_precondition_2state_32bit(
|
|
39
|
+
g_ptr,
|
|
40
|
+
p_ptr,
|
|
41
|
+
state1_ptr,
|
|
42
|
+
state2_ptr,
|
|
43
|
+
unorm_ptr,
|
|
44
|
+
beta1: tl.constexpr,
|
|
45
|
+
beta2: tl.constexpr,
|
|
46
|
+
eps: tl.constexpr,
|
|
47
|
+
weight_decay: tl.constexpr,
|
|
48
|
+
step,
|
|
49
|
+
beta1_step,
|
|
50
|
+
beta2_step,
|
|
51
|
+
lr,
|
|
52
|
+
gnorm_scale: tl.constexpr,
|
|
53
|
+
n_elements,
|
|
54
|
+
OPTIMIZER_ID: tl.constexpr,
|
|
55
|
+
BLOCK_SIZE: tl.constexpr,
|
|
56
|
+
N_PER_TH: tl.constexpr,
|
|
57
|
+
):
|
|
58
|
+
"""Preprocessing optimizer, computing update norm (2-state optimizer)"""
|
|
59
|
+
pid = tl.program_id(axis=0)
|
|
60
|
+
block_start_idx = pid * N_PER_TH
|
|
61
|
+
offsets = block_start_idx * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE * N_PER_TH)
|
|
62
|
+
mask = offsets < n_elements
|
|
63
|
+
|
|
64
|
+
g_vals = tl.load(g_ptr + offsets, mask=mask, other=0.0)
|
|
65
|
+
s1_vals = tl.load(state1_ptr + offsets, mask=mask, other=0.0)
|
|
66
|
+
s2_vals = tl.load(state2_ptr + offsets, mask=mask, other=0.0)
|
|
67
|
+
|
|
68
|
+
g_vals = gnorm_scale * g_vals
|
|
69
|
+
|
|
70
|
+
correction1 = 1.0 / (1.0 - beta1_step)
|
|
71
|
+
correction2 = 1.0 / (1.0 - beta2_step)
|
|
72
|
+
|
|
73
|
+
if OPTIMIZER_ID == 3: # ADAM
|
|
74
|
+
s1_vals = s1_vals * beta1 + (1.0 - beta1) * g_vals
|
|
75
|
+
s2_vals = s2_vals * beta2 + (1.0 - beta2) * g_vals * g_vals
|
|
76
|
+
|
|
77
|
+
s1_vals = s1_vals * correction1
|
|
78
|
+
s2_vals = s2_vals * correction2
|
|
79
|
+
|
|
80
|
+
update_vals = s1_vals / (tl.sqrt(s2_vals) + eps)
|
|
81
|
+
|
|
82
|
+
update_norm = update_vals * update_vals
|
|
83
|
+
|
|
84
|
+
elif OPTIMIZER_ID == 5: # ADEMAMIX
|
|
85
|
+
update_norm = s1_vals
|
|
86
|
+
|
|
87
|
+
total_norm = tl.sum(tl.where(mask, update_norm, 0.0))
|
|
88
|
+
|
|
89
|
+
tl.atomic_add(unorm_ptr, total_norm)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@triton.jit
|
|
93
|
+
def _optimizer_precondition_1state_32bit(
|
|
94
|
+
g_ptr,
|
|
95
|
+
p_ptr,
|
|
96
|
+
state1_ptr,
|
|
97
|
+
state2_ptr,
|
|
98
|
+
unorm_ptr,
|
|
99
|
+
beta1: tl.constexpr,
|
|
100
|
+
beta2: tl.constexpr,
|
|
101
|
+
eps: tl.constexpr,
|
|
102
|
+
weight_decay,
|
|
103
|
+
step,
|
|
104
|
+
beta1_step,
|
|
105
|
+
beta2_step,
|
|
106
|
+
lr,
|
|
107
|
+
gnorm_scale: tl.constexpr,
|
|
108
|
+
n_elements,
|
|
109
|
+
OPTIMIZER_ID: tl.constexpr,
|
|
110
|
+
BLOCK_SIZE: tl.constexpr,
|
|
111
|
+
N_PER_TH: tl.constexpr,
|
|
112
|
+
):
|
|
113
|
+
"""Preprocessing optimizer, computing update norm (1-state optimizer)"""
|
|
114
|
+
pid = tl.program_id(axis=0)
|
|
115
|
+
block_start_idx = pid * N_PER_TH
|
|
116
|
+
offsets = block_start_idx * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE * N_PER_TH)
|
|
117
|
+
mask = offsets < n_elements
|
|
118
|
+
|
|
119
|
+
g_vals = tl.load(g_ptr + offsets, mask=mask, other=0.0)
|
|
120
|
+
s1_vals = tl.load(state1_ptr + offsets, mask=mask, other=0.0)
|
|
121
|
+
|
|
122
|
+
g_vals = gnorm_scale * g_vals
|
|
123
|
+
|
|
124
|
+
if OPTIMIZER_ID == 0: # MOMENTUM
|
|
125
|
+
if step == 1:
|
|
126
|
+
# Cast to fp32 to avoid type mismatch: s1_vals is fp32 but g_vals may be fp16.
|
|
127
|
+
s1_vals = g_vals.to(tl.float32)
|
|
128
|
+
else:
|
|
129
|
+
s1_vals = s1_vals * beta1 + g_vals
|
|
130
|
+
update_norm = s1_vals * s1_vals
|
|
131
|
+
|
|
132
|
+
elif OPTIMIZER_ID == 4: # LION
|
|
133
|
+
s1_vals = s1_vals * beta2 + (1.0 - beta2) * g_vals
|
|
134
|
+
update_norm = s1_vals
|
|
135
|
+
|
|
136
|
+
elif OPTIMIZER_ID == 1: # RMSPROP
|
|
137
|
+
s1_vals = s1_vals * beta1 + (1.0 - beta1) * g_vals * g_vals
|
|
138
|
+
update_vals = g_vals / (tl.sqrt(s1_vals) + eps)
|
|
139
|
+
update_norm = update_vals * update_vals
|
|
140
|
+
|
|
141
|
+
elif OPTIMIZER_ID == 2: # ADAGRAD
|
|
142
|
+
s1_vals = s1_vals + g_vals * g_vals
|
|
143
|
+
update_vals = g_vals / (tl.sqrt(s1_vals) + eps)
|
|
144
|
+
update_norm = update_vals * update_vals
|
|
145
|
+
|
|
146
|
+
total_norm = tl.sum(tl.where(mask, update_norm, 0.0))
|
|
147
|
+
|
|
148
|
+
tl.atomic_add(unorm_ptr, total_norm)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@triton.jit
|
|
152
|
+
def _optimizer_update_2state_32bit_triton_kernel(
|
|
153
|
+
g_ptr,
|
|
154
|
+
p_ptr,
|
|
155
|
+
state1_ptr,
|
|
156
|
+
state2_ptr,
|
|
157
|
+
unorm_ptr,
|
|
158
|
+
max_unorm: tl.constexpr,
|
|
159
|
+
param_norm,
|
|
160
|
+
beta1: tl.constexpr,
|
|
161
|
+
beta2: tl.constexpr,
|
|
162
|
+
beta3,
|
|
163
|
+
alpha,
|
|
164
|
+
eps: tl.constexpr,
|
|
165
|
+
weight_decay: tl.constexpr,
|
|
166
|
+
step,
|
|
167
|
+
beta1_step,
|
|
168
|
+
beta2_step,
|
|
169
|
+
lr,
|
|
170
|
+
gnorm_scale: tl.constexpr,
|
|
171
|
+
skip_zeros,
|
|
172
|
+
n_elements,
|
|
173
|
+
OPTIMIZER_ID: tl.constexpr,
|
|
174
|
+
BLOCK_SIZE: tl.constexpr,
|
|
175
|
+
N_PER_TH: tl.constexpr,
|
|
176
|
+
):
|
|
177
|
+
"""2-state optimizer kernel"""
|
|
178
|
+
pid = tl.program_id(axis=0)
|
|
179
|
+
block_start_idx = pid * N_PER_TH
|
|
180
|
+
offsets = block_start_idx * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE * N_PER_TH)
|
|
181
|
+
mask = offsets < n_elements
|
|
182
|
+
|
|
183
|
+
g_vals = tl.load(g_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
184
|
+
p_vals = tl.load(p_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
185
|
+
s1_vals = tl.load(state1_ptr + offsets, mask=mask, other=0.0)
|
|
186
|
+
s2_vals = tl.load(state2_ptr + offsets, mask=mask, other=0.0)
|
|
187
|
+
|
|
188
|
+
if OPTIMIZER_ID == 5: # ADEMAMIX
|
|
189
|
+
s3_vals = tl.load(state1_ptr + n_elements + offsets, mask=mask, other=0.0)
|
|
190
|
+
|
|
191
|
+
g_vals = gnorm_scale * g_vals
|
|
192
|
+
|
|
193
|
+
update_scale = 1.0
|
|
194
|
+
if max_unorm > 0.0:
|
|
195
|
+
current_unorm = tl.sqrt(tl.load(unorm_ptr))
|
|
196
|
+
if current_unorm > max_unorm * param_norm:
|
|
197
|
+
update_scale = (max_unorm * param_norm) / current_unorm
|
|
198
|
+
|
|
199
|
+
if OPTIMIZER_ID == 3: # ADAM
|
|
200
|
+
s1_vals = s1_vals * beta1 + (1.0 - beta1) * g_vals
|
|
201
|
+
s2_vals = s2_vals * beta2 + (1.0 - beta2) * g_vals * g_vals
|
|
202
|
+
|
|
203
|
+
correction1 = 1.0 - beta1_step
|
|
204
|
+
correction2 = tl.sqrt(1.0 - beta2_step)
|
|
205
|
+
step_size = -lr * correction2 / correction1
|
|
206
|
+
|
|
207
|
+
if weight_decay > 0.0:
|
|
208
|
+
p_vals = p_vals * (1.0 - lr * weight_decay)
|
|
209
|
+
|
|
210
|
+
update_val = update_scale * step_size * (s1_vals / (tl.sqrt(s2_vals) + eps * correction2))
|
|
211
|
+
p_vals = p_vals + update_val
|
|
212
|
+
|
|
213
|
+
elif OPTIMIZER_ID == 5: # ADEMAMIX
|
|
214
|
+
s1_vals = s1_vals * beta1 + (1.0 - beta1) * g_vals # m1
|
|
215
|
+
s3_vals = s3_vals * beta3 + (1.0 - beta3) * g_vals # m2
|
|
216
|
+
s2_vals = s2_vals * beta2 + (1.0 - beta2) * g_vals * g_vals # nu
|
|
217
|
+
|
|
218
|
+
correction1 = 1.0 - beta1_step
|
|
219
|
+
correction2 = tl.sqrt(1.0 - beta2_step)
|
|
220
|
+
|
|
221
|
+
if weight_decay > 0.0:
|
|
222
|
+
p_vals = p_vals * (1.0 - lr * weight_decay)
|
|
223
|
+
|
|
224
|
+
mixed_momentum = (s1_vals / correction1) + (alpha * s3_vals)
|
|
225
|
+
adaptive_term = (tl.sqrt(s2_vals) / correction2) + eps
|
|
226
|
+
p_vals = p_vals - lr * (mixed_momentum / adaptive_term)
|
|
227
|
+
|
|
228
|
+
tl.store(p_ptr + offsets, p_vals, mask=mask)
|
|
229
|
+
tl.store(state1_ptr + offsets, s1_vals, mask=mask)
|
|
230
|
+
tl.store(state2_ptr + offsets, s2_vals, mask=mask)
|
|
231
|
+
|
|
232
|
+
if OPTIMIZER_ID == 5: # ADEMAMIX
|
|
233
|
+
tl.store(state1_ptr + n_elements + offsets, s3_vals, mask=mask)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@triton.jit
|
|
237
|
+
def _optimizer_update_1state_32bit_triton_kernel(
|
|
238
|
+
g_ptr,
|
|
239
|
+
p_ptr,
|
|
240
|
+
state1_ptr,
|
|
241
|
+
state2_ptr,
|
|
242
|
+
unorm_ptr,
|
|
243
|
+
max_unorm: tl.constexpr,
|
|
244
|
+
param_norm,
|
|
245
|
+
beta1: tl.constexpr,
|
|
246
|
+
beta2: tl.constexpr,
|
|
247
|
+
beta3,
|
|
248
|
+
alpha,
|
|
249
|
+
eps: tl.constexpr,
|
|
250
|
+
weight_decay: tl.constexpr,
|
|
251
|
+
step,
|
|
252
|
+
beta1_step,
|
|
253
|
+
beta2_step,
|
|
254
|
+
lr,
|
|
255
|
+
gnorm_scale: tl.constexpr,
|
|
256
|
+
skip_zeros,
|
|
257
|
+
n_elements,
|
|
258
|
+
OPTIMIZER_ID: tl.constexpr,
|
|
259
|
+
BLOCK_SIZE: tl.constexpr,
|
|
260
|
+
N_PER_TH: tl.constexpr,
|
|
261
|
+
):
|
|
262
|
+
"""1-state optimizer kernel"""
|
|
263
|
+
pid = tl.program_id(axis=0)
|
|
264
|
+
block_start_idx = pid * N_PER_TH
|
|
265
|
+
offsets = block_start_idx * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE * N_PER_TH)
|
|
266
|
+
mask = offsets < n_elements
|
|
267
|
+
|
|
268
|
+
g_vals = tl.load(g_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
269
|
+
p_vals = tl.load(p_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
270
|
+
s1_vals = tl.load(state1_ptr + offsets, mask=mask, other=0.0)
|
|
271
|
+
|
|
272
|
+
g_vals = gnorm_scale * g_vals
|
|
273
|
+
# Coupled (L2) weight decay: fold wd into the gradient. This is correct for
|
|
274
|
+
# MOMENTUM/RMSPROP/ADAGRAD, but NOT for LION (id 4), which uses *decoupled*
|
|
275
|
+
# (AdamW-style) weight decay applied to the param directly (see the LION branch
|
|
276
|
+
# below and Chen et al. 2023). LION is intentionally excluded here.
|
|
277
|
+
if OPTIMIZER_ID != 4 and weight_decay > 0.0:
|
|
278
|
+
g_vals = g_vals + p_vals * weight_decay
|
|
279
|
+
|
|
280
|
+
update_scale = 1.0
|
|
281
|
+
if max_unorm > 0.0:
|
|
282
|
+
current_unorm = tl.sqrt(tl.load(unorm_ptr))
|
|
283
|
+
if current_unorm > max_unorm * param_norm + eps:
|
|
284
|
+
update_scale = (max_unorm * param_norm + eps) / current_unorm
|
|
285
|
+
|
|
286
|
+
if OPTIMIZER_ID == 0: # MOMENTUM
|
|
287
|
+
if step == 1:
|
|
288
|
+
s1_vals = g_vals
|
|
289
|
+
else:
|
|
290
|
+
s1_vals = s1_vals * beta1 + g_vals
|
|
291
|
+
|
|
292
|
+
update_val = update_scale * (-lr * s1_vals)
|
|
293
|
+
p_vals = p_vals + update_val
|
|
294
|
+
|
|
295
|
+
elif OPTIMIZER_ID == 4: # LION
|
|
296
|
+
# Lion uses decoupled weight decay: shrink the param directly (p *= 1 - lr*wd)
|
|
297
|
+
# rather than folding wd into the gradient. Matches the 8-bit blockwise kernel,
|
|
298
|
+
# the default/cpu backends, and the Lion paper (Chen et al. 2023).
|
|
299
|
+
if weight_decay > 0.0:
|
|
300
|
+
p_vals = p_vals * (1.0 - lr * weight_decay)
|
|
301
|
+
|
|
302
|
+
momentum_update = s1_vals * beta1 + (1.0 - beta1) * g_vals
|
|
303
|
+
update_val = update_scale * lr * tl.where(momentum_update > 0, 1.0, tl.where(momentum_update < 0, -1.0, 0.0))
|
|
304
|
+
p_vals = p_vals - update_val
|
|
305
|
+
|
|
306
|
+
s1_vals = s1_vals * beta2 + (1.0 - beta2) * g_vals
|
|
307
|
+
|
|
308
|
+
elif OPTIMIZER_ID == 1: # RMSPROP
|
|
309
|
+
s1_vals = s1_vals * beta1 + (1.0 - beta1) * g_vals * g_vals
|
|
310
|
+
|
|
311
|
+
update_val = update_scale * lr * g_vals / (tl.sqrt(s1_vals) + eps)
|
|
312
|
+
p_vals = p_vals - update_val
|
|
313
|
+
|
|
314
|
+
elif OPTIMIZER_ID == 2: # ADAGRAD
|
|
315
|
+
s1_vals = s1_vals + g_vals * g_vals
|
|
316
|
+
|
|
317
|
+
update_val = lr * g_vals / (tl.sqrt(s1_vals) + eps)
|
|
318
|
+
p_vals = p_vals - update_val
|
|
319
|
+
|
|
320
|
+
tl.store(p_ptr + offsets, p_vals, mask=mask)
|
|
321
|
+
tl.store(state1_ptr + offsets, s1_vals, mask=mask)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
name2optimizer_32bit_fn = {
|
|
325
|
+
"adam": {
|
|
326
|
+
"preprocess": _optimizer_precondition_2state_32bit,
|
|
327
|
+
"update": _optimizer_update_2state_32bit_triton_kernel,
|
|
328
|
+
},
|
|
329
|
+
"lamb": {
|
|
330
|
+
"preprocess": _optimizer_precondition_2state_32bit,
|
|
331
|
+
"update": _optimizer_update_2state_32bit_triton_kernel,
|
|
332
|
+
},
|
|
333
|
+
"ademamix": {
|
|
334
|
+
"preprocess": _optimizer_precondition_2state_32bit,
|
|
335
|
+
"update": _optimizer_update_2state_32bit_triton_kernel,
|
|
336
|
+
},
|
|
337
|
+
"momentum": {
|
|
338
|
+
"preprocess": _optimizer_precondition_1state_32bit,
|
|
339
|
+
"update": _optimizer_update_1state_32bit_triton_kernel,
|
|
340
|
+
},
|
|
341
|
+
"lars": {
|
|
342
|
+
"preprocess": _optimizer_precondition_1state_32bit,
|
|
343
|
+
"update": _optimizer_update_1state_32bit_triton_kernel,
|
|
344
|
+
},
|
|
345
|
+
"rmsprop": {
|
|
346
|
+
"preprocess": _optimizer_precondition_1state_32bit,
|
|
347
|
+
"update": _optimizer_update_1state_32bit_triton_kernel,
|
|
348
|
+
},
|
|
349
|
+
"adagrad": {
|
|
350
|
+
"preprocess": _optimizer_precondition_1state_32bit,
|
|
351
|
+
"update": _optimizer_update_1state_32bit_triton_kernel,
|
|
352
|
+
},
|
|
353
|
+
"lion": {
|
|
354
|
+
"preprocess": _optimizer_precondition_1state_32bit,
|
|
355
|
+
"update": _optimizer_update_1state_32bit_triton_kernel,
|
|
356
|
+
},
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def optimizer_update_32bit_impl(
|
|
361
|
+
optimizer_name: str,
|
|
362
|
+
g: torch.Tensor,
|
|
363
|
+
p: torch.Tensor,
|
|
364
|
+
state1: torch.Tensor,
|
|
365
|
+
state2: Optional[torch.Tensor],
|
|
366
|
+
unorm_vec: Optional[torch.Tensor],
|
|
367
|
+
max_unorm: float,
|
|
368
|
+
param_norm: float,
|
|
369
|
+
beta1: float,
|
|
370
|
+
beta2: float,
|
|
371
|
+
beta3: float,
|
|
372
|
+
alpha: float,
|
|
373
|
+
eps: float,
|
|
374
|
+
weight_decay: float,
|
|
375
|
+
step: int,
|
|
376
|
+
lr: float,
|
|
377
|
+
gnorm_scale: float = 1.0,
|
|
378
|
+
skip_zeros=False,
|
|
379
|
+
) -> None:
|
|
380
|
+
"""
|
|
381
|
+
32-bit optimizer implemented by Triton
|
|
382
|
+
"""
|
|
383
|
+
if skip_zeros:
|
|
384
|
+
raise NotImplementedError("skip_zeros is not supported on XPU yet")
|
|
385
|
+
|
|
386
|
+
BLOCK_SIZE = 256
|
|
387
|
+
N_PER_TH = 1 # Number of blocks processed per thread.
|
|
388
|
+
grid = (triton.cdiv(p.numel(), BLOCK_SIZE * N_PER_TH),)
|
|
389
|
+
optimizer_id = name2optimizer_id[optimizer_name]
|
|
390
|
+
fn_preprocess = name2optimizer_32bit_fn[optimizer_name]["preprocess"]
|
|
391
|
+
fn_update = name2optimizer_32bit_fn[optimizer_name]["update"]
|
|
392
|
+
|
|
393
|
+
# In torch=2.7 on XPU there is an issue with libdevice.pow, leading to an error.
|
|
394
|
+
# For backwards compatibility we precompute the bias correction factors.
|
|
395
|
+
beta1_step = beta1**step
|
|
396
|
+
beta2_step = beta2**step
|
|
397
|
+
|
|
398
|
+
if optimizer_name == "lion":
|
|
399
|
+
fn_update[grid](
|
|
400
|
+
g,
|
|
401
|
+
p,
|
|
402
|
+
state1,
|
|
403
|
+
state2,
|
|
404
|
+
unorm_vec,
|
|
405
|
+
max_unorm,
|
|
406
|
+
param_norm,
|
|
407
|
+
beta1,
|
|
408
|
+
beta2,
|
|
409
|
+
beta3,
|
|
410
|
+
alpha,
|
|
411
|
+
eps,
|
|
412
|
+
weight_decay,
|
|
413
|
+
step,
|
|
414
|
+
beta1_step,
|
|
415
|
+
beta2_step,
|
|
416
|
+
lr,
|
|
417
|
+
gnorm_scale,
|
|
418
|
+
skip_zeros,
|
|
419
|
+
p.numel(),
|
|
420
|
+
optimizer_id,
|
|
421
|
+
BLOCK_SIZE,
|
|
422
|
+
N_PER_TH,
|
|
423
|
+
num_warps=2,
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
if max_unorm > 0.0:
|
|
427
|
+
unorm_vec.zero_()
|
|
428
|
+
fn_preprocess[grid](
|
|
429
|
+
g,
|
|
430
|
+
p,
|
|
431
|
+
state1,
|
|
432
|
+
state2,
|
|
433
|
+
unorm_vec,
|
|
434
|
+
beta1,
|
|
435
|
+
beta2,
|
|
436
|
+
eps,
|
|
437
|
+
weight_decay,
|
|
438
|
+
step,
|
|
439
|
+
beta1_step,
|
|
440
|
+
beta2_step,
|
|
441
|
+
lr,
|
|
442
|
+
gnorm_scale,
|
|
443
|
+
p.numel(),
|
|
444
|
+
optimizer_id,
|
|
445
|
+
BLOCK_SIZE,
|
|
446
|
+
N_PER_TH,
|
|
447
|
+
num_warps=2,
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
else:
|
|
451
|
+
if max_unorm > 0.0:
|
|
452
|
+
unorm_vec.zero_()
|
|
453
|
+
fn_preprocess[grid](
|
|
454
|
+
g,
|
|
455
|
+
p,
|
|
456
|
+
state1,
|
|
457
|
+
state2,
|
|
458
|
+
unorm_vec,
|
|
459
|
+
beta1,
|
|
460
|
+
beta2,
|
|
461
|
+
eps,
|
|
462
|
+
weight_decay,
|
|
463
|
+
step,
|
|
464
|
+
beta1_step,
|
|
465
|
+
beta2_step,
|
|
466
|
+
lr,
|
|
467
|
+
gnorm_scale,
|
|
468
|
+
p.numel(),
|
|
469
|
+
optimizer_id,
|
|
470
|
+
BLOCK_SIZE,
|
|
471
|
+
N_PER_TH,
|
|
472
|
+
num_warps=2,
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
fn_update[grid](
|
|
476
|
+
g,
|
|
477
|
+
p,
|
|
478
|
+
state1,
|
|
479
|
+
state2,
|
|
480
|
+
unorm_vec,
|
|
481
|
+
max_unorm,
|
|
482
|
+
param_norm,
|
|
483
|
+
beta1,
|
|
484
|
+
beta2,
|
|
485
|
+
beta3,
|
|
486
|
+
alpha,
|
|
487
|
+
eps,
|
|
488
|
+
weight_decay,
|
|
489
|
+
step,
|
|
490
|
+
beta1_step,
|
|
491
|
+
beta2_step,
|
|
492
|
+
lr,
|
|
493
|
+
gnorm_scale,
|
|
494
|
+
skip_zeros,
|
|
495
|
+
p.numel(),
|
|
496
|
+
optimizer_id,
|
|
497
|
+
BLOCK_SIZE,
|
|
498
|
+
N_PER_TH,
|
|
499
|
+
num_warps=2,
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
###########################################
|
|
504
|
+
# Pure torch implementation for reference #
|
|
505
|
+
###########################################
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
@torch.compile
|
|
509
|
+
def _dequantize_blockwise_pytorch(
|
|
510
|
+
A: torch.Tensor,
|
|
511
|
+
absmax: torch.Tensor,
|
|
512
|
+
code: torch.Tensor,
|
|
513
|
+
blocksize: int,
|
|
514
|
+
dtype: torch.dtype,
|
|
515
|
+
) -> torch.Tensor:
|
|
516
|
+
"""
|
|
517
|
+
Pure PyTorch reference implementation for block-wise dequantization.
|
|
518
|
+
"""
|
|
519
|
+
if A.numel() == 0:
|
|
520
|
+
return torch.empty_like(A, dtype=dtype)
|
|
521
|
+
|
|
522
|
+
A_flat = A.flatten()
|
|
523
|
+
num_elements = A_flat.numel()
|
|
524
|
+
|
|
525
|
+
dequantized_flat = code.to(A.device)[A_flat.long()].to(dtype)
|
|
526
|
+
|
|
527
|
+
num_blocks = math.ceil(num_elements / blocksize)
|
|
528
|
+
pad_len = num_blocks * blocksize - num_elements
|
|
529
|
+
if pad_len > 0:
|
|
530
|
+
dequantized_flat = torch.nn.functional.pad(dequantized_flat, (0, pad_len))
|
|
531
|
+
|
|
532
|
+
dequantized_blocks = dequantized_flat.reshape(num_blocks, blocksize)
|
|
533
|
+
|
|
534
|
+
rescaled_blocks = dequantized_blocks * absmax.unsqueeze(1).to(dtype)
|
|
535
|
+
|
|
536
|
+
rescaled_flat = rescaled_blocks.flatten()
|
|
537
|
+
if pad_len > 0:
|
|
538
|
+
rescaled_flat = rescaled_flat[:-pad_len]
|
|
539
|
+
|
|
540
|
+
return rescaled_flat.reshape(A.shape)
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
@torch.compile
|
|
544
|
+
def _quantize_blockwise_pytorch(
|
|
545
|
+
A: torch.Tensor,
|
|
546
|
+
code: torch.Tensor,
|
|
547
|
+
blocksize: int,
|
|
548
|
+
) -> tuple[torch.Tensor, torch.Tensor]:
|
|
549
|
+
"""
|
|
550
|
+
Pure PyTorch reference implementation for block-wise quantization.
|
|
551
|
+
"""
|
|
552
|
+
if A.numel() == 0:
|
|
553
|
+
return torch.empty_like(A, dtype=torch.uint8), torch.empty(0, dtype=torch.float32, device=A.device)
|
|
554
|
+
|
|
555
|
+
A_flat = A.flatten()
|
|
556
|
+
num_elements = A_flat.numel()
|
|
557
|
+
|
|
558
|
+
num_blocks = math.ceil(num_elements / blocksize)
|
|
559
|
+
|
|
560
|
+
pad_len = num_blocks * blocksize - num_elements
|
|
561
|
+
if pad_len > 0:
|
|
562
|
+
A_flat = torch.nn.functional.pad(A_flat, (0, pad_len))
|
|
563
|
+
|
|
564
|
+
A_blocks = A_flat.reshape(num_blocks, blocksize)
|
|
565
|
+
|
|
566
|
+
absmax = torch.max(torch.abs(A_blocks), dim=1, keepdim=True)[0]
|
|
567
|
+
absmax[absmax == 0] = 1.0
|
|
568
|
+
|
|
569
|
+
scaled_blocks = A_blocks / absmax
|
|
570
|
+
|
|
571
|
+
# Inefficient but straightforward quantization, takes a lot of memory
|
|
572
|
+
diff = torch.abs(scaled_blocks.unsqueeze(2) - code.to(A.device))
|
|
573
|
+
quantized_indices = torch.argmin(diff, dim=2).to(torch.uint8)
|
|
574
|
+
|
|
575
|
+
quantized_flat = quantized_indices.flatten()
|
|
576
|
+
if pad_len > 0:
|
|
577
|
+
quantized_flat = quantized_flat[:-pad_len]
|
|
578
|
+
|
|
579
|
+
return quantized_flat.reshape(A.shape), absmax.flatten()
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
# Main updated function
|
|
583
|
+
def optimizer_update_8bit_blockwise_pytorch(
|
|
584
|
+
p: torch.Tensor,
|
|
585
|
+
g: torch.Tensor,
|
|
586
|
+
state1: torch.Tensor,
|
|
587
|
+
state2: Optional[torch.Tensor],
|
|
588
|
+
beta1: float,
|
|
589
|
+
beta2: float,
|
|
590
|
+
beta3: float, # ADEMIX
|
|
591
|
+
alpha: float, # ADEMIX
|
|
592
|
+
eps: float,
|
|
593
|
+
step: int,
|
|
594
|
+
lr: float,
|
|
595
|
+
qmap1: torch.Tensor,
|
|
596
|
+
qmap2: Optional[torch.Tensor],
|
|
597
|
+
absmax1: torch.Tensor,
|
|
598
|
+
absmax2: Optional[torch.Tensor],
|
|
599
|
+
weight_decay: float,
|
|
600
|
+
gnorm_scale: float,
|
|
601
|
+
skip_zeros: bool,
|
|
602
|
+
# ADEMIX
|
|
603
|
+
*,
|
|
604
|
+
optimizer_name: str,
|
|
605
|
+
) -> None:
|
|
606
|
+
"""
|
|
607
|
+
Pure PyTorch implementation of the 8-bit block-wise optimizer update step.
|
|
608
|
+
This version ensures high-precision updates for float16 parameters.
|
|
609
|
+
"""
|
|
610
|
+
if skip_zeros:
|
|
611
|
+
raise ValueError("skip_zeros is not supported on XPU yet.")
|
|
612
|
+
|
|
613
|
+
blocksize = 256
|
|
614
|
+
|
|
615
|
+
with torch.no_grad():
|
|
616
|
+
# Dequantize states to perform updates in 32-bit precision
|
|
617
|
+
if optimizer_name == "ademamix" and absmax1.ndim == 2:
|
|
618
|
+
# For AdEMAMix, state1 holds two EMAs, so absmax1 is stacked.
|
|
619
|
+
s1_1_fp32 = _dequantize_blockwise_pytorch(state1[0], absmax1[0], qmap1, blocksize, torch.float32)
|
|
620
|
+
s1_2_fp32 = _dequantize_blockwise_pytorch(state1[1], absmax1[1], qmap1, blocksize, torch.float32)
|
|
621
|
+
state1_fp32 = torch.stack([s1_1_fp32, s1_2_fp32])
|
|
622
|
+
else:
|
|
623
|
+
state1_fp32 = _dequantize_blockwise_pytorch(state1, absmax1, qmap1, blocksize, torch.float32)
|
|
624
|
+
|
|
625
|
+
state2_fp32 = None
|
|
626
|
+
if state2 is not None:
|
|
627
|
+
state2_fp32 = _dequantize_blockwise_pytorch(state2, absmax2, qmap2, blocksize, torch.float32)
|
|
628
|
+
|
|
629
|
+
grad = g.float() * gnorm_scale
|
|
630
|
+
|
|
631
|
+
# Create a 32-bit copy of the parameter for high-precision updates
|
|
632
|
+
p_fp32 = p.data.float()
|
|
633
|
+
|
|
634
|
+
if optimizer_name == "adam":
|
|
635
|
+
state1_fp32.mul_(beta1).add_(grad, alpha=1.0 - beta1)
|
|
636
|
+
state2_fp32.mul_(beta2).addcmul_(grad, grad, value=1.0 - beta2)
|
|
637
|
+
|
|
638
|
+
bias_correction1 = 1.0 - beta1**step
|
|
639
|
+
bias_correction2 = 1.0 - beta2**step
|
|
640
|
+
|
|
641
|
+
denom = (state2_fp32.sqrt() / math.sqrt(bias_correction2)).add_(eps)
|
|
642
|
+
|
|
643
|
+
if weight_decay > 0.0:
|
|
644
|
+
p_fp32.mul_(1.0 - lr * weight_decay)
|
|
645
|
+
p_fp32.addcdiv_(state1_fp32, denom, value=-lr / bias_correction1)
|
|
646
|
+
|
|
647
|
+
elif optimizer_name == "ademamix":
|
|
648
|
+
m1_fp32, m2_fp32 = state1_fp32[0], state1_fp32[1]
|
|
649
|
+
nu_fp32 = state2_fp32
|
|
650
|
+
|
|
651
|
+
m1_fp32.mul_(beta1).add_(grad, alpha=1.0 - beta1)
|
|
652
|
+
m2_fp32.mul_(beta3).add_(grad, alpha=1.0 - beta3)
|
|
653
|
+
nu_fp32.mul_(beta2).addcmul_(grad, grad, value=1.0 - beta2)
|
|
654
|
+
|
|
655
|
+
bias_correction1 = 1.0 - beta1**step
|
|
656
|
+
bias_correction2 = math.sqrt(1.0 - beta2**step)
|
|
657
|
+
|
|
658
|
+
update = (m1_fp32 / bias_correction1 + alpha * m2_fp32) / (nu_fp32.sqrt() / bias_correction2 + eps)
|
|
659
|
+
|
|
660
|
+
if weight_decay > 0.0:
|
|
661
|
+
p_fp32.mul_(1.0 - lr * weight_decay)
|
|
662
|
+
|
|
663
|
+
p_fp32.add_(update, alpha=-lr)
|
|
664
|
+
state1_fp32 = torch.stack([m1_fp32, m2_fp32])
|
|
665
|
+
|
|
666
|
+
elif optimizer_name == "momentum":
|
|
667
|
+
grad.add_(p_fp32, alpha=weight_decay)
|
|
668
|
+
if step == 1:
|
|
669
|
+
state1_fp32.copy_(grad)
|
|
670
|
+
else:
|
|
671
|
+
state1_fp32.mul_(beta1).add_(grad)
|
|
672
|
+
p_fp32.add_(state1_fp32, alpha=-lr)
|
|
673
|
+
|
|
674
|
+
elif optimizer_name == "rmsprop":
|
|
675
|
+
grad.add_(p_fp32, alpha=weight_decay)
|
|
676
|
+
state1_fp32.mul_(beta1).addcmul_(grad, grad, value=1.0 - beta1)
|
|
677
|
+
p_fp32.addcdiv_(grad, state1_fp32.sqrt().add_(eps), value=-lr)
|
|
678
|
+
|
|
679
|
+
elif optimizer_name == "lion":
|
|
680
|
+
if weight_decay > 0.0:
|
|
681
|
+
p_fp32.mul_(1.0 - lr * weight_decay)
|
|
682
|
+
|
|
683
|
+
update_dir = torch.sign(state1_fp32.mul(beta1) + grad.mul(1.0 - beta1))
|
|
684
|
+
p_fp32.add_(update_dir, alpha=-lr)
|
|
685
|
+
|
|
686
|
+
state1_fp32.mul_(beta2).add_(grad, alpha=1.0 - beta2)
|
|
687
|
+
|
|
688
|
+
elif optimizer_name == "adagrad":
|
|
689
|
+
grad.add_(p_fp32, alpha=weight_decay)
|
|
690
|
+
state1_fp32.addcmul_(grad, grad, value=1.0)
|
|
691
|
+
p_fp32.addcdiv_(grad, state1_fp32.sqrt().add_(eps), value=-lr)
|
|
692
|
+
|
|
693
|
+
else:
|
|
694
|
+
raise NotImplementedError(
|
|
695
|
+
f"Pure PyTorch implementation for optimizer '{optimizer_name}' is not available."
|
|
696
|
+
)
|
|
697
|
+
|
|
698
|
+
# Copy the updated 32-bit parameter back to the original tensor
|
|
699
|
+
p.data.copy_(p_fp32)
|
|
700
|
+
|
|
701
|
+
# Re-quantize states and update state tensors in-place
|
|
702
|
+
if optimizer_name == "ademamix":
|
|
703
|
+
new_m1_8bit, new_absmax_m1 = _quantize_blockwise_pytorch(state1_fp32[0], qmap1, blocksize)
|
|
704
|
+
new_m2_8bit, new_absmax_m2 = _quantize_blockwise_pytorch(state1_fp32[1], qmap1, blocksize)
|
|
705
|
+
state1[0].copy_(new_m1_8bit)
|
|
706
|
+
state1[1].copy_(new_m2_8bit)
|
|
707
|
+
absmax1[0].copy_(new_absmax_m1)
|
|
708
|
+
absmax1[1].copy_(new_absmax_m2)
|
|
709
|
+
|
|
710
|
+
new_state2_8bit, new_absmax2 = _quantize_blockwise_pytorch(state2_fp32, qmap2, blocksize)
|
|
711
|
+
state2.copy_(new_state2_8bit)
|
|
712
|
+
absmax2.copy_(new_absmax2)
|
|
713
|
+
else:
|
|
714
|
+
new_state1_8bit, new_absmax1 = _quantize_blockwise_pytorch(state1_fp32, qmap1, blocksize)
|
|
715
|
+
state1.copy_(new_state1_8bit)
|
|
716
|
+
absmax1.copy_(new_absmax1)
|
|
717
|
+
|
|
718
|
+
if state2_fp32 is not None:
|
|
719
|
+
new_state2_8bit, new_absmax2 = _quantize_blockwise_pytorch(state2_fp32, qmap2, blocksize)
|
|
720
|
+
state2.copy_(new_state2_8bit)
|
|
721
|
+
absmax2.copy_(new_absmax2)
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
#######################################
|
|
725
|
+
# Mixed torch + triton implementation #
|
|
726
|
+
#######################################
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
# Much more memory efficient due to using triton for quantization/dequantization
|
|
730
|
+
def optimizer_update_8bit_blockwise_triton_quant(
|
|
731
|
+
p: torch.Tensor,
|
|
732
|
+
g: torch.Tensor,
|
|
733
|
+
state1: torch.Tensor,
|
|
734
|
+
state2: Optional[torch.Tensor],
|
|
735
|
+
beta1: float,
|
|
736
|
+
beta2: float,
|
|
737
|
+
beta3: float, # ADEMIX
|
|
738
|
+
alpha: float, # ADEMIX
|
|
739
|
+
eps: float,
|
|
740
|
+
step: int,
|
|
741
|
+
lr: float,
|
|
742
|
+
qmap1: torch.Tensor,
|
|
743
|
+
qmap2: Optional[torch.Tensor],
|
|
744
|
+
absmax1: torch.Tensor,
|
|
745
|
+
absmax2: Optional[torch.Tensor],
|
|
746
|
+
weight_decay: float,
|
|
747
|
+
gnorm_scale: float,
|
|
748
|
+
skip_zeros: bool,
|
|
749
|
+
# ADEMIX
|
|
750
|
+
*,
|
|
751
|
+
optimizer_name: str,
|
|
752
|
+
) -> None:
|
|
753
|
+
"""
|
|
754
|
+
Pure PyTorch implementation of the 8-bit block-wise optimizer update step.
|
|
755
|
+
This version ensures high-precision updates for float16 parameters.
|
|
756
|
+
"""
|
|
757
|
+
if skip_zeros and not torch.any(g):
|
|
758
|
+
return
|
|
759
|
+
|
|
760
|
+
blocksize = 256
|
|
761
|
+
grad = g.float() * gnorm_scale
|
|
762
|
+
|
|
763
|
+
with torch.no_grad():
|
|
764
|
+
# Create a 32-bit copy of the parameter for high-precision updates
|
|
765
|
+
p_fp32 = p.data.float()
|
|
766
|
+
|
|
767
|
+
# Dequantize states to perform updates in 32-bit precision
|
|
768
|
+
if optimizer_name == "ademamix" and absmax1.ndim == 2:
|
|
769
|
+
# For AdEMAMix, state1 holds two EMAs, so absmax1 is stacked.
|
|
770
|
+
s1_1_fp32 = dequant_8bit_blockwise(state1[0], absmax1[0], qmap1, blocksize, dtype=torch.float32)
|
|
771
|
+
s1_2_fp32 = dequant_8bit_blockwise(state1[1], absmax1[1], qmap1, blocksize, dtype=torch.float32)
|
|
772
|
+
state1_fp32 = torch.stack([s1_1_fp32, s1_2_fp32])
|
|
773
|
+
else:
|
|
774
|
+
state1_fp32 = dequant_8bit_blockwise(state1, absmax1, qmap1, blocksize, dtype=torch.float32)
|
|
775
|
+
|
|
776
|
+
state2_fp32 = None
|
|
777
|
+
if state2 is not None:
|
|
778
|
+
state2_fp32 = dequant_8bit_blockwise(state2, absmax2, qmap2, blocksize, dtype=torch.float32)
|
|
779
|
+
|
|
780
|
+
# Apply optimizer-specific update logic
|
|
781
|
+
if optimizer_name == "adam":
|
|
782
|
+
if weight_decay > 0.0:
|
|
783
|
+
p_fp32.mul_(1.0 - lr * weight_decay)
|
|
784
|
+
|
|
785
|
+
state1_fp32.mul_(beta1).add_(grad, alpha=1.0 - beta1)
|
|
786
|
+
state2_fp32.mul_(beta2).addcmul_(grad, grad, value=1.0 - beta2)
|
|
787
|
+
|
|
788
|
+
bias_correction1 = 1.0 - beta1**step
|
|
789
|
+
bias_correction2 = 1.0 - beta2**step
|
|
790
|
+
|
|
791
|
+
denom = (state2_fp32.sqrt() / math.sqrt(bias_correction2)).add_(eps)
|
|
792
|
+
p_fp32.addcdiv_(state1_fp32, denom, value=-lr / bias_correction1)
|
|
793
|
+
|
|
794
|
+
elif optimizer_name == "ademamix":
|
|
795
|
+
m1_fp32, m2_fp32 = state1_fp32[0], state1_fp32[1]
|
|
796
|
+
nu_fp32 = state2_fp32
|
|
797
|
+
|
|
798
|
+
m1_fp32.mul_(beta1).add_(grad, alpha=1.0 - beta1)
|
|
799
|
+
m2_fp32.mul_(beta3).add_(grad, alpha=1.0 - beta3)
|
|
800
|
+
nu_fp32.mul_(beta2).addcmul_(grad, grad, value=1.0 - beta2)
|
|
801
|
+
|
|
802
|
+
bias_correction1 = 1.0 - beta1**step
|
|
803
|
+
bias_correction2 = math.sqrt(1.0 - beta2**step)
|
|
804
|
+
|
|
805
|
+
update = (m1_fp32 / bias_correction1 + alpha * m2_fp32) / (nu_fp32.sqrt() / bias_correction2 + eps)
|
|
806
|
+
|
|
807
|
+
if weight_decay > 0.0:
|
|
808
|
+
p_fp32.mul_(1.0 - lr * weight_decay)
|
|
809
|
+
|
|
810
|
+
p_fp32.add_(update, alpha=-lr)
|
|
811
|
+
state1_fp32 = torch.stack([m1_fp32, m2_fp32])
|
|
812
|
+
|
|
813
|
+
elif optimizer_name == "momentum":
|
|
814
|
+
grad.add_(p_fp32, alpha=weight_decay)
|
|
815
|
+
if step == 1:
|
|
816
|
+
state1_fp32.copy_(grad)
|
|
817
|
+
else:
|
|
818
|
+
state1_fp32.mul_(beta1).add_(grad)
|
|
819
|
+
p_fp32.add_(state1_fp32, alpha=-lr)
|
|
820
|
+
|
|
821
|
+
elif optimizer_name == "rmsprop":
|
|
822
|
+
grad.add_(p_fp32, alpha=weight_decay)
|
|
823
|
+
state1_fp32.mul_(beta1).addcmul_(grad, grad, value=1.0 - beta1)
|
|
824
|
+
p_fp32.addcdiv_(grad, state1_fp32.sqrt().add_(eps), value=-lr)
|
|
825
|
+
|
|
826
|
+
elif optimizer_name == "lion":
|
|
827
|
+
if weight_decay > 0.0:
|
|
828
|
+
p_fp32.mul_(1.0 - lr * weight_decay)
|
|
829
|
+
|
|
830
|
+
update_dir = torch.sign(state1_fp32.mul(beta1) + grad.mul(1.0 - beta1))
|
|
831
|
+
p_fp32.add_(update_dir, alpha=-lr)
|
|
832
|
+
|
|
833
|
+
state1_fp32.mul_(beta2).add_(grad, alpha=1.0 - beta2)
|
|
834
|
+
|
|
835
|
+
elif optimizer_name == "adagrad":
|
|
836
|
+
grad.add_(p_fp32, alpha=weight_decay)
|
|
837
|
+
state1_fp32.addcmul_(grad, grad, value=1.0)
|
|
838
|
+
p_fp32.addcdiv_(grad, state1_fp32.sqrt().add_(eps), value=-lr)
|
|
839
|
+
|
|
840
|
+
else:
|
|
841
|
+
raise NotImplementedError(
|
|
842
|
+
f"Pure PyTorch implementation for optimizer '{optimizer_name}' is not available."
|
|
843
|
+
)
|
|
844
|
+
|
|
845
|
+
# Copy the updated 32-bit parameter back to the original tensor
|
|
846
|
+
p.data.copy_(p_fp32)
|
|
847
|
+
|
|
848
|
+
# Re-quantize states and update state tensors in-place
|
|
849
|
+
if optimizer_name == "ademamix":
|
|
850
|
+
new_m1_8bit, new_absmax_m1 = quantize_blockwise_triton(state1_fp32[0], qmap1, blocksize)
|
|
851
|
+
new_m2_8bit, new_absmax_m2 = quantize_blockwise_triton(state1_fp32[1], qmap1, blocksize)
|
|
852
|
+
state1[0].copy_(new_m1_8bit)
|
|
853
|
+
state1[1].copy_(new_m2_8bit)
|
|
854
|
+
absmax1[0].copy_(new_absmax_m1)
|
|
855
|
+
absmax1[1].copy_(new_absmax_m2)
|
|
856
|
+
|
|
857
|
+
new_state2_8bit, new_absmax2 = quantize_blockwise_triton(state2_fp32, qmap2, blocksize)
|
|
858
|
+
state2.copy_(new_state2_8bit)
|
|
859
|
+
absmax2.copy_(new_absmax2)
|
|
860
|
+
else:
|
|
861
|
+
new_state1_8bit, new_absmax1 = quantize_blockwise_triton(state1_fp32, qmap1, blocksize)
|
|
862
|
+
state1.copy_(new_state1_8bit)
|
|
863
|
+
absmax1.copy_(new_absmax1)
|
|
864
|
+
|
|
865
|
+
if state2_fp32 is not None:
|
|
866
|
+
new_state2_8bit, new_absmax2 = quantize_blockwise_triton(state2_fp32, qmap2, blocksize)
|
|
867
|
+
state2.copy_(new_state2_8bit)
|
|
868
|
+
absmax2.copy_(new_absmax2)
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
#########################
|
|
872
|
+
# Triton implementation #
|
|
873
|
+
#########################
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
@triton.jit
|
|
877
|
+
def _optimizer_update_1state_8bit_blockwise_triton_kernel(
|
|
878
|
+
# Tensors
|
|
879
|
+
p_ptr,
|
|
880
|
+
g_ptr,
|
|
881
|
+
state1_ptr,
|
|
882
|
+
state2_ptr,
|
|
883
|
+
beta1: tl.constexpr,
|
|
884
|
+
beta2: tl.constexpr,
|
|
885
|
+
beta3,
|
|
886
|
+
alpha,
|
|
887
|
+
eps: tl.constexpr,
|
|
888
|
+
step,
|
|
889
|
+
beta1_step,
|
|
890
|
+
beta2_step,
|
|
891
|
+
lr,
|
|
892
|
+
qmap1_ptr,
|
|
893
|
+
qmap2_ptr,
|
|
894
|
+
absmax1_ptr,
|
|
895
|
+
absmax2_ptr,
|
|
896
|
+
weight_decay,
|
|
897
|
+
gnorm_scale,
|
|
898
|
+
# Meta-parameters
|
|
899
|
+
n_elements,
|
|
900
|
+
BLOCK_SIZE_N: tl.constexpr,
|
|
901
|
+
N_PER_TH: tl.constexpr,
|
|
902
|
+
OPTIMIZER_ID: tl.constexpr,
|
|
903
|
+
):
|
|
904
|
+
"""
|
|
905
|
+
Triton kernel for 8-bit optimizers that use one momentum state.
|
|
906
|
+
Supports: Momentum, RMSprop, Adagrad, Lion.
|
|
907
|
+
"""
|
|
908
|
+
# 1. Boilerplate: pid, offsets, mask
|
|
909
|
+
pid = tl.program_id(axis=0)
|
|
910
|
+
block_start_idx = pid * N_PER_TH
|
|
911
|
+
offsets = block_start_idx * BLOCK_SIZE_N + tl.arange(0, BLOCK_SIZE_N * N_PER_TH)
|
|
912
|
+
mask = offsets < n_elements
|
|
913
|
+
|
|
914
|
+
# 2. Load and dequantize tensors
|
|
915
|
+
g = tl.load(g_ptr + offsets, mask=mask, other=0.0).to(tl.float32) * gnorm_scale
|
|
916
|
+
p = tl.load(p_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
917
|
+
s1 = dequant_8bit_blockwise_kernel_util(state1_ptr, offsets, qmap1_ptr, absmax1_ptr, mask, BLOCK_SIZE_N)
|
|
918
|
+
|
|
919
|
+
# 3. Optimizer-specific updates
|
|
920
|
+
# LION
|
|
921
|
+
if weight_decay > 0.0 and OPTIMIZER_ID == 2:
|
|
922
|
+
p *= 1.0 - lr * weight_decay
|
|
923
|
+
# Apply weight decay for momentum, rmsprop, adagrad
|
|
924
|
+
elif weight_decay > 0.0:
|
|
925
|
+
g += p * weight_decay
|
|
926
|
+
|
|
927
|
+
# Momentum update
|
|
928
|
+
if OPTIMIZER_ID == 0: # MOMENTUM
|
|
929
|
+
if step == 1:
|
|
930
|
+
s1 = g
|
|
931
|
+
else:
|
|
932
|
+
s1 = s1 * beta1 + g
|
|
933
|
+
p -= lr * s1
|
|
934
|
+
|
|
935
|
+
# RMSprop update
|
|
936
|
+
elif OPTIMIZER_ID == 1: # RMSPROP
|
|
937
|
+
s1 = s1 * beta1 + (1.0 - beta1) * g * g
|
|
938
|
+
p -= lr * (g / (tl.sqrt(s1) + eps))
|
|
939
|
+
|
|
940
|
+
# Adagrad update
|
|
941
|
+
elif OPTIMIZER_ID == 2: # ADAGRAD
|
|
942
|
+
s1 += g * g
|
|
943
|
+
p -= lr * (g / (tl.sqrt(s1) + eps))
|
|
944
|
+
|
|
945
|
+
# Lion update
|
|
946
|
+
elif OPTIMIZER_ID == 4: # LION
|
|
947
|
+
val = s1 * beta1 + (1.0 - beta1) * g
|
|
948
|
+
update = tl.where(val > 0.0, 1.0, tl.where(val < 0.0, -1.0, 0.0))
|
|
949
|
+
p -= lr * update
|
|
950
|
+
s1 = s1 * beta2 + (1.0 - beta2) * g
|
|
951
|
+
|
|
952
|
+
# 4. Store updated parameter and requantized state
|
|
953
|
+
tl.store(p_ptr + offsets, p.to(p_ptr.dtype.element_ty), mask=mask)
|
|
954
|
+
s1_codes, new_absmax1 = quantize_8bit_blockwise_kernel_util(s1, qmap1_ptr, 256, BLOCK_SIZE_N, N_PER_TH)
|
|
955
|
+
tl.store(state1_ptr + offsets, s1_codes, mask=mask)
|
|
956
|
+
tl.store(absmax1_ptr + block_start_idx + tl.arange(0, N_PER_TH), new_absmax1)
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
@triton.jit
|
|
960
|
+
def _optimizer_update_2state_8bit_blockwise_triton_kernel(
|
|
961
|
+
# Tensors
|
|
962
|
+
p_ptr,
|
|
963
|
+
g_ptr,
|
|
964
|
+
state1_ptr,
|
|
965
|
+
state2_ptr,
|
|
966
|
+
beta1: tl.constexpr,
|
|
967
|
+
beta2: tl.constexpr,
|
|
968
|
+
# ademamix changes alpha and beta3
|
|
969
|
+
beta3,
|
|
970
|
+
# ademamix changes alpha and beta3
|
|
971
|
+
alpha,
|
|
972
|
+
eps: tl.constexpr,
|
|
973
|
+
step,
|
|
974
|
+
beta1_step,
|
|
975
|
+
beta2_step,
|
|
976
|
+
lr,
|
|
977
|
+
qmap1_ptr,
|
|
978
|
+
qmap2_ptr,
|
|
979
|
+
absmax1_ptr,
|
|
980
|
+
absmax2_ptr,
|
|
981
|
+
weight_decay: tl.constexpr,
|
|
982
|
+
gnorm_scale: tl.constexpr,
|
|
983
|
+
# Meta-parameters
|
|
984
|
+
n_elements,
|
|
985
|
+
BLOCK_SIZE_N: tl.constexpr,
|
|
986
|
+
N_PER_TH: tl.constexpr,
|
|
987
|
+
OPTIMIZER_ID: tl.constexpr,
|
|
988
|
+
):
|
|
989
|
+
"""
|
|
990
|
+
Triton kernel for 8-bit optimizers that use two momentum states.
|
|
991
|
+
Supports: Adam, AdEMAMix.
|
|
992
|
+
"""
|
|
993
|
+
# 1. Boilerplate: pid, offsets, mask
|
|
994
|
+
pid = tl.program_id(axis=0)
|
|
995
|
+
block_start_idx = pid * N_PER_TH
|
|
996
|
+
offsets = block_start_idx * BLOCK_SIZE_N + tl.arange(0, BLOCK_SIZE_N * N_PER_TH)
|
|
997
|
+
mask = offsets < n_elements
|
|
998
|
+
|
|
999
|
+
# 2. Load and dequantize tensors
|
|
1000
|
+
g = tl.load(g_ptr + offsets, mask=mask, other=0.0).to(tl.float32) * gnorm_scale
|
|
1001
|
+
p = tl.load(p_ptr + offsets, mask=mask, other=0.0).to(tl.float32)
|
|
1002
|
+
|
|
1003
|
+
# 3. Optimizer-specific updates
|
|
1004
|
+
if OPTIMIZER_ID == 3: # ADAM
|
|
1005
|
+
s1 = dequant_8bit_blockwise_kernel_util(state1_ptr, offsets, qmap1_ptr, absmax1_ptr, mask, BLOCK_SIZE_N)
|
|
1006
|
+
s2 = dequant_8bit_blockwise_kernel_util(state2_ptr, offsets, qmap2_ptr, absmax2_ptr, mask, BLOCK_SIZE_N)
|
|
1007
|
+
|
|
1008
|
+
s1 = s1 * beta1 + (1.0 - beta1) * g
|
|
1009
|
+
s2 = s2 * beta2 + (1.0 - beta2) * g * g
|
|
1010
|
+
|
|
1011
|
+
# In torch=2.7 on XPU there is an issue with libdevice.pow, leading to an error.
|
|
1012
|
+
# For backwards compatibility we precompute the bias correction factors.
|
|
1013
|
+
# bias_correction1 = 1.0 - libdevice.pow(beta1, step)
|
|
1014
|
+
# bias_correction2 = 1.0 - libdevice.pow(beta2, step)
|
|
1015
|
+
bias_correction1 = 1.0 - beta1_step
|
|
1016
|
+
bias_correction2 = 1.0 - beta2_step
|
|
1017
|
+
|
|
1018
|
+
if weight_decay > 0.0:
|
|
1019
|
+
p *= 1.0 - lr * weight_decay
|
|
1020
|
+
|
|
1021
|
+
denom = tl.sqrt(s2) / tl.sqrt(bias_correction2) + eps
|
|
1022
|
+
p -= (lr / bias_correction1) * (s1 / denom)
|
|
1023
|
+
|
|
1024
|
+
# Store updated parameter
|
|
1025
|
+
tl.store(p_ptr + offsets, p.to(p_ptr.dtype.element_ty), mask=mask)
|
|
1026
|
+
|
|
1027
|
+
# Requantize and store states
|
|
1028
|
+
s1_codes, new_absmax1 = quantize_8bit_blockwise_kernel_util(s1, qmap1_ptr, 256, BLOCK_SIZE_N, N_PER_TH)
|
|
1029
|
+
tl.store(state1_ptr + offsets, s1_codes, mask=mask)
|
|
1030
|
+
tl.store(absmax1_ptr + block_start_idx + tl.arange(0, N_PER_TH), new_absmax1)
|
|
1031
|
+
|
|
1032
|
+
s2_codes, new_absmax2 = quantize_8bit_blockwise_kernel_util(s2, qmap2_ptr, 256, BLOCK_SIZE_N, N_PER_TH)
|
|
1033
|
+
tl.store(state2_ptr + offsets, s2_codes, mask=mask)
|
|
1034
|
+
tl.store(absmax2_ptr + block_start_idx + tl.arange(0, N_PER_TH), new_absmax2)
|
|
1035
|
+
|
|
1036
|
+
elif OPTIMIZER_ID == 5: # ADEMAMIX
|
|
1037
|
+
# AdEMAMix has a stacked state1 (m1, m2) and state2 (nu)
|
|
1038
|
+
m1 = dequant_8bit_blockwise_kernel_util(state1_ptr, offsets, qmap1_ptr, absmax1_ptr, mask, BLOCK_SIZE_N)
|
|
1039
|
+
m2 = dequant_8bit_blockwise_kernel_util(
|
|
1040
|
+
state1_ptr + n_elements,
|
|
1041
|
+
offsets,
|
|
1042
|
+
qmap1_ptr,
|
|
1043
|
+
absmax1_ptr + n_elements // BLOCK_SIZE_N,
|
|
1044
|
+
mask,
|
|
1045
|
+
BLOCK_SIZE_N,
|
|
1046
|
+
)
|
|
1047
|
+
nu = dequant_8bit_blockwise_kernel_util(state2_ptr, offsets, qmap2_ptr, absmax2_ptr, mask, BLOCK_SIZE_N)
|
|
1048
|
+
|
|
1049
|
+
m1 = m1 * beta1 + (1.0 - beta1) * g
|
|
1050
|
+
m2 = m2 * beta3 + (1.0 - beta3) * g
|
|
1051
|
+
nu = nu * beta2 + (1.0 - beta2) * g * g
|
|
1052
|
+
|
|
1053
|
+
# In torch=2.7 on XPU there is an issue with libdevice.pow, leading to an error.
|
|
1054
|
+
# For backwards compatibility we precompute the bias correction factors.
|
|
1055
|
+
# bias_correction1 = 1.0 - libdevice.pow(beta1, step)
|
|
1056
|
+
# bias_correction2 = tl.sqrt(1.0 - libdevice.pow(beta2, step))
|
|
1057
|
+
bias_correction1 = 1.0 - beta1_step
|
|
1058
|
+
bias_correction2 = tl.sqrt(1.0 - beta2_step)
|
|
1059
|
+
|
|
1060
|
+
update = (m1 / bias_correction1 + alpha * m2) / (tl.sqrt(nu) / bias_correction2 + eps)
|
|
1061
|
+
|
|
1062
|
+
if weight_decay > 0.0:
|
|
1063
|
+
p *= 1.0 - lr * weight_decay
|
|
1064
|
+
|
|
1065
|
+
p -= lr * update
|
|
1066
|
+
|
|
1067
|
+
# Store updated parameter
|
|
1068
|
+
tl.store(p_ptr + offsets, p.to(p_ptr.dtype.element_ty), mask=mask)
|
|
1069
|
+
|
|
1070
|
+
# Requantize and store all three states
|
|
1071
|
+
m1_codes, new_absmax_m1 = quantize_8bit_blockwise_kernel_util(m1, qmap1_ptr, 256, BLOCK_SIZE_N, N_PER_TH)
|
|
1072
|
+
tl.store(state1_ptr + offsets, m1_codes, mask=mask)
|
|
1073
|
+
tl.store(absmax1_ptr + block_start_idx + tl.arange(0, N_PER_TH), new_absmax_m1)
|
|
1074
|
+
|
|
1075
|
+
m2_codes, new_absmax_m2 = quantize_8bit_blockwise_kernel_util(m2, qmap1_ptr, 256, BLOCK_SIZE_N, N_PER_TH)
|
|
1076
|
+
tl.store(state1_ptr + n_elements + offsets, m2_codes, mask=mask)
|
|
1077
|
+
tl.store(
|
|
1078
|
+
absmax1_ptr + block_start_idx + tl.arange(0, N_PER_TH) + n_elements // BLOCK_SIZE_N,
|
|
1079
|
+
new_absmax_m2,
|
|
1080
|
+
)
|
|
1081
|
+
|
|
1082
|
+
nu_codes, new_absmax_nu = quantize_8bit_blockwise_kernel_util(nu, qmap2_ptr, 256, BLOCK_SIZE_N, N_PER_TH)
|
|
1083
|
+
tl.store(state2_ptr + offsets, nu_codes, mask=mask)
|
|
1084
|
+
tl.store(absmax2_ptr + block_start_idx + tl.arange(0, N_PER_TH), new_absmax_nu)
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
name2optimizer_fn = {
|
|
1088
|
+
"momentum": _optimizer_update_1state_8bit_blockwise_triton_kernel,
|
|
1089
|
+
"lars": _optimizer_update_1state_8bit_blockwise_triton_kernel,
|
|
1090
|
+
"rmsprop": _optimizer_update_1state_8bit_blockwise_triton_kernel,
|
|
1091
|
+
"adagrad": _optimizer_update_1state_8bit_blockwise_triton_kernel,
|
|
1092
|
+
"adam": _optimizer_update_2state_8bit_blockwise_triton_kernel,
|
|
1093
|
+
"lamb": _optimizer_update_2state_8bit_blockwise_triton_kernel,
|
|
1094
|
+
"lion": _optimizer_update_1state_8bit_blockwise_triton_kernel,
|
|
1095
|
+
"ademamix": _optimizer_update_2state_8bit_blockwise_triton_kernel,
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
def optimizer_update_8bit_blockwise_impl(
|
|
1100
|
+
optimizer_name: str,
|
|
1101
|
+
g: torch.Tensor,
|
|
1102
|
+
p: torch.Tensor,
|
|
1103
|
+
state1: torch.Tensor,
|
|
1104
|
+
state2: Optional[torch.Tensor],
|
|
1105
|
+
beta1: float,
|
|
1106
|
+
beta2: float,
|
|
1107
|
+
beta3: float,
|
|
1108
|
+
alpha: float,
|
|
1109
|
+
eps: float,
|
|
1110
|
+
step: int,
|
|
1111
|
+
lr: float,
|
|
1112
|
+
qmap1: torch.Tensor,
|
|
1113
|
+
qmap2: Optional[torch.Tensor],
|
|
1114
|
+
absmax1: torch.Tensor,
|
|
1115
|
+
absmax2: Optional[torch.Tensor],
|
|
1116
|
+
weight_decay: float = 0.0,
|
|
1117
|
+
gnorm_scale: float = 1.0,
|
|
1118
|
+
skip_zeros=False,
|
|
1119
|
+
) -> None:
|
|
1120
|
+
if skip_zeros:
|
|
1121
|
+
raise NotImplementedError("skip_zeros is not supported on XPU yet")
|
|
1122
|
+
|
|
1123
|
+
if optimizer_name == "ademamix":
|
|
1124
|
+
# Handle AdEMAMIX's stacked state tensors
|
|
1125
|
+
if state1.dim() < 2 or state1.shape[0] != 2:
|
|
1126
|
+
raise ValueError(
|
|
1127
|
+
f"For ademamix, state1 must be a stacked tensor of shape (2, ...), but got {state1.shape}"
|
|
1128
|
+
)
|
|
1129
|
+
if absmax1.dim() < 2 or absmax1.shape[0] != 2:
|
|
1130
|
+
raise ValueError(
|
|
1131
|
+
f"For ademamix, absmax1 must be a stacked tensor of shape (2, ...), but got {absmax1.shape}"
|
|
1132
|
+
)
|
|
1133
|
+
|
|
1134
|
+
BLOCK_SIZE = 256
|
|
1135
|
+
N_PER_TH = 1 # Number of blocks processed per thread.
|
|
1136
|
+
grid = (triton.cdiv(p.numel(), BLOCK_SIZE * N_PER_TH),)
|
|
1137
|
+
fn = name2optimizer_fn[optimizer_name]
|
|
1138
|
+
optimizer_id = name2optimizer_id[optimizer_name]
|
|
1139
|
+
|
|
1140
|
+
# In torch=2.7 on XPU there is an issue with libdevice.pow, leading to an error.
|
|
1141
|
+
# For backwards compatibility we precompute the bias correction factors.
|
|
1142
|
+
beta1_step = beta1**step
|
|
1143
|
+
beta2_step = beta2**step
|
|
1144
|
+
|
|
1145
|
+
fn[grid](
|
|
1146
|
+
p,
|
|
1147
|
+
g,
|
|
1148
|
+
state1,
|
|
1149
|
+
state2,
|
|
1150
|
+
beta1,
|
|
1151
|
+
beta2,
|
|
1152
|
+
beta3,
|
|
1153
|
+
alpha,
|
|
1154
|
+
eps,
|
|
1155
|
+
step,
|
|
1156
|
+
beta1_step,
|
|
1157
|
+
beta2_step,
|
|
1158
|
+
lr,
|
|
1159
|
+
qmap1,
|
|
1160
|
+
qmap2,
|
|
1161
|
+
absmax1,
|
|
1162
|
+
absmax2,
|
|
1163
|
+
weight_decay,
|
|
1164
|
+
gnorm_scale,
|
|
1165
|
+
p.numel(),
|
|
1166
|
+
BLOCK_SIZE_N=BLOCK_SIZE,
|
|
1167
|
+
N_PER_TH=N_PER_TH,
|
|
1168
|
+
OPTIMIZER_ID=optimizer_id,
|
|
1169
|
+
num_warps=2,
|
|
1170
|
+
)
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
# optimizer_update_8bit_blockwise_impl = optimizer_update_8bit_blockwise_pytorch
|
|
1174
|
+
# optimizer_update_8bit_blockwise_impl = torch.compile(optimizer_update_8bit_blockwise_pytorch_impl)
|
|
1175
|
+
# optimizer_update_8bit_blockwise_impl = optimizer_update_8bit_blockwise_triton_quant
|
|
1176
|
+
# optimizer_update_8bit_blockwise_impl = torch.compile(optimizer_update_8bit_blockwise_triton_quant)
|
|
1177
|
+
optimizer_update_8bit_blockwise_impl = optimizer_update_8bit_blockwise_impl
|