Scott/Codex commited on
Commit ·
9c90574
1
Parent(s): aa3d8cc
Tune DBlock backward-math speed line
Browse files- README.md +3 -0
- dblocks_train.py +35 -6
- nB300_agillm4_vram_dblock.py +6 -0
- relaunch_agillm4_dblock_sg2.sh +4 -4
README.md
CHANGED
|
@@ -94,3 +94,6 @@ Quality target update 2026-05-29: Scott clarified the previous AGILLM run was ro
|
|
| 94 |
|
| 95 |
|
| 96 |
License: Apache-2.0 (matching the upstream method).
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
|
| 96 |
License: Apache-2.0 (matching the upstream method).
|
| 97 |
+
|
| 98 |
+
Backward-math speed update 2026-05-29: live profiling confirmed the expensive path is AR transformer backward/recompute, not fused CE, data loading, or optimizer step. A clean context/batch sweep found B6/L1024 gives the best raw throughput among quality-preserving candidates (6144 tokens/step, ~3.3k tok/s profiler math) while keeping a 1024-token context. A second objective-mix sweep tested a harder experimental path: reducing full causal AR steps from 85% to 70% and moving the probability mass to SAT/NAT (`--dblock_ar_prob 0.70 --dblock_sat_prob 0.15 --dblock_nat_prob 0.15`). Clean profiler math reached ~3440 tok/s, and the live relaunch now uses B6/L1024 + ar70. The relaunch script intentionally unsets `PYTORCH_CUDA_ALLOC_CONF` because the previous expandable-segments allocator reserved ~23 GB and caused memory-pressure slowdown on this shape; without it, the live line returns to ~15.1 GB tensor peak / ~16.5-17.4 GB observed VRAM. This is experimental by design: it trades some AR-step density for faster multi-objective DBlock training while preserving checkpoint warm start and the 55 tokens/param target.
|
| 99 |
+
|
dblocks_train.py
CHANGED
|
@@ -182,21 +182,50 @@ def _update_stats(state, bi, loss_value):
|
|
| 182 |
state["step"] = int(state.get("step", 0)) + 1
|
| 183 |
|
| 184 |
|
| 185 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
if use_checkpoint:
|
| 187 |
return _ck.checkpoint(lambda y, block=block: block(y, mask), x, use_reentrant=False)
|
|
|
|
|
|
|
|
|
|
| 188 |
return block(x, mask)
|
| 189 |
|
| 190 |
|
| 191 |
-
def _dblock_checkpoint_this_layer(args, base_enabled, layer_pos):
|
| 192 |
if not base_enabled:
|
| 193 |
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
stride = int(getattr(args, "dblock_checkpoint_stride", 1) or 1)
|
| 195 |
if stride <= 0:
|
| 196 |
return False
|
| 197 |
if stride == 1:
|
| 198 |
return True
|
| 199 |
-
return (
|
| 200 |
|
| 201 |
|
| 202 |
def _sample_token_loss_inputs(hidden, targets, max_tokens):
|
|
@@ -293,7 +322,7 @@ def _dblock_step(core, ar_h, sat_h, nat_h, opt, scaler, args, ids, state):
|
|
| 293 |
zt = emb + sig[:, None, None] * torch.randn_like(emb)
|
| 294 |
h = ci * zt
|
| 295 |
for lpos, li in enumerate(layers):
|
| 296 |
-
h = _run_block(core.blocks[li], h, causal, _dblock_checkpoint_this_layer(args, use_layer_checkpoint, lpos))
|
| 297 |
Dn = core.ln(cs * zt + co * h)
|
| 298 |
_profile_toc(state, "ar_forward", _t)
|
| 299 |
_t = _profile_tic(prof)
|
|
@@ -316,7 +345,7 @@ def _dblock_step(core, ar_h, sat_h, nat_h, opt, scaler, args, ids, state):
|
|
| 316 |
zt2 = emb2 + sig[:, None, None] * torch.randn_like(emb2)
|
| 317 |
h2 = ci * zt2
|
| 318 |
for lpos, li in enumerate(layers):
|
| 319 |
-
h2 = _run_block(core.blocks[li], h2, smask, _dblock_checkpoint_this_layer(args, use_layer_checkpoint, lpos))
|
| 320 |
Ds = core.ln(cs * zt2 + co * h2)
|
| 321 |
last = Ds[:, -SATB:]
|
| 322 |
_profile_toc(state, "sat_forward", _t)
|
|
@@ -355,7 +384,7 @@ def _dblock_step(core, ar_h, sat_h, nat_h, opt, scaler, args, ids, state):
|
|
| 355 |
nat_in[m] = M.BLANK
|
| 356 |
hn = core.emb(nat_in)
|
| 357 |
for lpos, li in enumerate(layers):
|
| 358 |
-
hn = _run_block(core.blocks[li], hn, None, _dblock_checkpoint_this_layer(args, use_layer_checkpoint, lpos))
|
| 359 |
Dnat = core.ln(hn)
|
| 360 |
_profile_toc(state, "nat_forward", _t)
|
| 361 |
_t = _profile_tic(prof)
|
|
|
|
| 182 |
state["step"] = int(state.get("step", 0)) + 1
|
| 183 |
|
| 184 |
|
| 185 |
+
def _activation_offload_enabled(args):
|
| 186 |
+
return bool(getattr(args, "dblock_activation_offload", False)) and torch.cuda.is_available()
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
def _activation_offload_hooks(args):
|
| 190 |
+
min_bytes = int(float(getattr(args, "dblock_activation_offload_min_mb", 1.0) or 1.0) * 1024 * 1024)
|
| 191 |
+
|
| 192 |
+
def pack(t):
|
| 193 |
+
if not torch.is_tensor(t) or not t.is_cuda or not t.is_floating_point() or t.numel() * t.element_size() < min_bytes:
|
| 194 |
+
return t
|
| 195 |
+
return ("cpu_offload", t.device, t.detach().to("cpu", non_blocking=True))
|
| 196 |
+
|
| 197 |
+
def unpack(x):
|
| 198 |
+
if isinstance(x, tuple) and len(x) == 3 and x[0] == "cpu_offload":
|
| 199 |
+
_, dev, cpu_t = x
|
| 200 |
+
return cpu_t.to(dev, non_blocking=True)
|
| 201 |
+
return x
|
| 202 |
+
|
| 203 |
+
return torch.autograd.graph.saved_tensors_hooks(pack, unpack)
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
def _run_block(block, x, mask, use_checkpoint, args=None):
|
| 207 |
if use_checkpoint:
|
| 208 |
return _ck.checkpoint(lambda y, block=block: block(y, mask), x, use_reentrant=False)
|
| 209 |
+
if args is not None and _activation_offload_enabled(args):
|
| 210 |
+
with _activation_offload_hooks(args):
|
| 211 |
+
return block(x, mask)
|
| 212 |
return block(x, mask)
|
| 213 |
|
| 214 |
|
| 215 |
+
def _dblock_checkpoint_this_layer(args, base_enabled, layer_pos, layer_count=None):
|
| 216 |
if not base_enabled:
|
| 217 |
return False
|
| 218 |
+
pos = int(layer_pos)
|
| 219 |
+
count = int(layer_count or 0)
|
| 220 |
+
skip_tail = max(0, int(getattr(args, "dblock_checkpoint_skip_tail", 0) or 0))
|
| 221 |
+
if skip_tail > 0 and count > 0 and pos >= max(0, count - skip_tail):
|
| 222 |
+
return False
|
| 223 |
stride = int(getattr(args, "dblock_checkpoint_stride", 1) or 1)
|
| 224 |
if stride <= 0:
|
| 225 |
return False
|
| 226 |
if stride == 1:
|
| 227 |
return True
|
| 228 |
+
return (pos % stride) == 0
|
| 229 |
|
| 230 |
|
| 231 |
def _sample_token_loss_inputs(hidden, targets, max_tokens):
|
|
|
|
| 322 |
zt = emb + sig[:, None, None] * torch.randn_like(emb)
|
| 323 |
h = ci * zt
|
| 324 |
for lpos, li in enumerate(layers):
|
| 325 |
+
h = _run_block(core.blocks[li], h, causal, _dblock_checkpoint_this_layer(args, use_layer_checkpoint, lpos, len(layers)), args)
|
| 326 |
Dn = core.ln(cs * zt + co * h)
|
| 327 |
_profile_toc(state, "ar_forward", _t)
|
| 328 |
_t = _profile_tic(prof)
|
|
|
|
| 345 |
zt2 = emb2 + sig[:, None, None] * torch.randn_like(emb2)
|
| 346 |
h2 = ci * zt2
|
| 347 |
for lpos, li in enumerate(layers):
|
| 348 |
+
h2 = _run_block(core.blocks[li], h2, smask, _dblock_checkpoint_this_layer(args, use_layer_checkpoint, lpos, len(layers)), args)
|
| 349 |
Ds = core.ln(cs * zt2 + co * h2)
|
| 350 |
last = Ds[:, -SATB:]
|
| 351 |
_profile_toc(state, "sat_forward", _t)
|
|
|
|
| 384 |
nat_in[m] = M.BLANK
|
| 385 |
hn = core.emb(nat_in)
|
| 386 |
for lpos, li in enumerate(layers):
|
| 387 |
+
hn = _run_block(core.blocks[li], hn, None, _dblock_checkpoint_this_layer(args, use_layer_checkpoint, lpos, len(layers)), args)
|
| 388 |
Dnat = core.ln(hn)
|
| 389 |
_profile_toc(state, "nat_forward", _t)
|
| 390 |
_t = _profile_tic(prof)
|
nB300_agillm4_vram_dblock.py
CHANGED
|
@@ -3039,6 +3039,12 @@ def main():
|
|
| 3039 |
help="Print DBlock block/loss/VRAM diagnostics every N DBlock steps; 0 disables.")
|
| 3040 |
tr.add_argument("--dblock_checkpoint_stride", type=int, default=1,
|
| 3041 |
help="With --grad_checkpoint in --dblock mode, checkpoint one layer every N selected block layers; 1=all layers, 2=alternate, 0=off.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3042 |
tr.add_argument("--dblock_sigma_curriculum_steps", type=int, default=2000,
|
| 3043 |
help="Warm sigma ranges from easy to full span over this many DBlock steps; 0 disables.")
|
| 3044 |
tr.add_argument("--dblock_edm_wmax", type=float, default=5.0,
|
|
|
|
| 3039 |
help="Print DBlock block/loss/VRAM diagnostics every N DBlock steps; 0 disables.")
|
| 3040 |
tr.add_argument("--dblock_checkpoint_stride", type=int, default=1,
|
| 3041 |
help="With --grad_checkpoint in --dblock mode, checkpoint one layer every N selected block layers; 1=all layers, 2=alternate, 0=off.")
|
| 3042 |
+
tr.add_argument("--dblock_checkpoint_skip_tail", type=int, default=0,
|
| 3043 |
+
help="Experimental DBlock speed knob: do not checkpoint this many final layers in the selected block, reducing backward recompute at higher VRAM cost.")
|
| 3044 |
+
tr.add_argument("--dblock_activation_offload", action="store_true",
|
| 3045 |
+
help="Experimental DBlock speed knob: for non-checkpointed block layers, offload saved backward tensors to CPU RAM instead of recomputing.")
|
| 3046 |
+
tr.add_argument("--dblock_activation_offload_min_mb", type=float, default=1.0,
|
| 3047 |
+
help="Minimum CUDA tensor size in MB to offload under --dblock_activation_offload.")
|
| 3048 |
tr.add_argument("--dblock_sigma_curriculum_steps", type=int, default=2000,
|
| 3049 |
help="Warm sigma ranges from easy to full span over this many DBlock steps; 0 disables.")
|
| 3050 |
tr.add_argument("--dblock_edm_wmax", type=float, default=5.0,
|
relaunch_agillm4_dblock_sg2.sh
CHANGED
|
@@ -4,20 +4,20 @@ set -Eeuo pipefail
|
|
| 4 |
cd /workspace/agillm-4
|
| 5 |
export TOKENIZERS_PARALLELISM=false
|
| 6 |
export TOKENIZER_ID="${TOKENIZER_ID:-deepseek-ai/DeepSeek-V4-Pro}"
|
| 7 |
-
|
| 8 |
export AGILLM_ATTN_BACKEND=sublinear
|
| 9 |
[ -f /root/.cache/huggingface/token ] && { export HF_TOKEN="$(tr -d '\r\n' </root/.cache/huggingface/token)"; export HUGGING_FACE_HUB_TOKEN="$HF_TOKEN"; }
|
| 10 |
SAVE_DIR=/workspace/agillm4_4090_ckpts
|
| 11 |
TOKEN_PARAM_RATIO="${TOKEN_PARAM_RATIO:-55}"
|
| 12 |
CKPT="$(ls -1t "$SAVE_DIR"/pretrain_step*.pt 2>/dev/null | head -1)"
|
| 13 |
exec >> /workspace/agillm4_floor_train.log 2>&1
|
| 14 |
-
echo "RELAUNCH_AGILLM4_DBLOCK_SG2 $(date -u +%Y-%m-%dT%H:%M:%SZ) resume=$CKPT (quality ratio55 +
|
| 15 |
exec python -u nB300_agillm4.py train --preset agillm4_floor --resume "$CKPT" \
|
| 16 |
--dblock --dblock_blocks 4 --dblock_schedule loss_balanced --dblock_warmup_steps 16 \
|
| 17 |
--dblock_sigma_curriculum_steps 2000 --dblock_log_every 25 --dblock_objective_mode stochastic \
|
| 18 |
-
--dblock_ar_prob 0.
|
| 19 |
--dblock_ar_loss_tokens 512 --dblock_sat_loss_tokens 0 --dblock_nat_loss_tokens 512 \
|
| 20 |
-
--tie_weights --batch_size
|
| 21 |
--sublinear_window 128 --sublinear_stride 128 --sublinear_max_anchors 128 --sublinear_chunk 128 \
|
| 22 |
--sublinear_sinks 4 --sublinear_recent_anchors 64 --no-sublinear_pooled_landmarks \
|
| 23 |
--grad_checkpoint --dblock_checkpoint_stride 1 --optimizer paged_adamw8bit --sat_every 4 --nat_every 4 --nat_max_tokens 768 --nat_mask_ratio 0.5 \
|
|
|
|
| 4 |
cd /workspace/agillm-4
|
| 5 |
export TOKENIZERS_PARALLELISM=false
|
| 6 |
export TOKENIZER_ID="${TOKENIZER_ID:-deepseek-ai/DeepSeek-V4-Pro}"
|
| 7 |
+
unset PYTORCH_CUDA_ALLOC_CONF # B6/L1024 ar70: avoid near-full allocator reservation slowdown
|
| 8 |
export AGILLM_ATTN_BACKEND=sublinear
|
| 9 |
[ -f /root/.cache/huggingface/token ] && { export HF_TOKEN="$(tr -d '\r\n' </root/.cache/huggingface/token)"; export HUGGING_FACE_HUB_TOKEN="$HF_TOKEN"; }
|
| 10 |
SAVE_DIR=/workspace/agillm4_4090_ckpts
|
| 11 |
TOKEN_PARAM_RATIO="${TOKEN_PARAM_RATIO:-55}"
|
| 12 |
CKPT="$(ls -1t "$SAVE_DIR"/pretrain_step*.pt 2>/dev/null | head -1)"
|
| 13 |
exec >> /workspace/agillm4_floor_train.log 2>&1
|
| 14 |
+
echo "RELAUNCH_AGILLM4_DBLOCK_SG2 $(date -u +%Y-%m-%dT%H:%M:%SZ) resume=$CKPT (quality ratio55 + B6/L1024 + ar70 backward-math + sublinear v2)"
|
| 15 |
exec python -u nB300_agillm4.py train --preset agillm4_floor --resume "$CKPT" \
|
| 16 |
--dblock --dblock_blocks 4 --dblock_schedule loss_balanced --dblock_warmup_steps 16 \
|
| 17 |
--dblock_sigma_curriculum_steps 2000 --dblock_log_every 25 --dblock_objective_mode stochastic \
|
| 18 |
+
--dblock_ar_prob 0.70 --dblock_sat_prob 0.15 --dblock_nat_prob 0.15 \
|
| 19 |
--dblock_ar_loss_tokens 512 --dblock_sat_loss_tokens 0 --dblock_nat_loss_tokens 512 \
|
| 20 |
+
--tie_weights --batch_size 6 --block 1024 --amp --attn_backend sublinear \
|
| 21 |
--sublinear_window 128 --sublinear_stride 128 --sublinear_max_anchors 128 --sublinear_chunk 128 \
|
| 22 |
--sublinear_sinks 4 --sublinear_recent_anchors 64 --no-sublinear_pooled_landmarks \
|
| 23 |
--grad_checkpoint --dblock_checkpoint_stride 1 --optimizer paged_adamw8bit --sat_every 4 --nat_every 4 --nat_max_tokens 768 --nat_mask_ratio 0.5 \
|