Skip to content

Commit 226517f

Browse files
committed
cleanup(multi-lora): remove unused native config surface
1 parent 7fdc01e commit 226517f

8 files changed

Lines changed: 93 additions & 191 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ ckpts/
2222
coverage.json
2323
.coverage*
2424
test_assets/
25+
tests/unit/unit_results.json
26+
tests/unit/unit_results/
2527
.nrl_remote_map.json
2628
.nrl_remote_state.json
2729
# Test biproducts

examples/configs/recipes/multi_lora/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ policy:
3232
```
3333
3434
Key knobs (see header comment in `base.yaml`): `policy.max_grad_norm`,
35-
`multi_lora.enabled`, `single_dataset`, per-adapter LoRA/optimizer settings
36-
under `multi_lora.adapters[]`.
35+
`multi_lora.enabled`, `single_dataset`, shared LoRA/optimizer settings under
36+
`policy`, and per-adapter datasets under `multi_lora.adapters[]`.
3737

3838
## Running
3939

@@ -85,7 +85,7 @@ NOUSNET_INIT_IMPORT_DIR read canonical shards (all runs of a battery)
8585
NOUSNET_INIT_IMPORT_SLOT which shard slot a single-LoRA run imports (0-3)
8686
NOUSNET_PER_ADAPTER_GRAD_CLIP clip each adapter's grads independently (multi)
8787
NOUSNET_FORCE_PAD_TO pad every microbatch to a fixed length (parity)
88-
NOUSNET_DETERMINISTIC(_SEED) torch deterministic algorithms + seed
88+
NOUSNET_DETERMINISTIC_SEED torch/numpy/Python deterministic seed
8989
```
9090

9191
Unit tests: `pytest tests/unit/models/multi_lora/ -q` (CPU-only, no GPU

examples/configs/recipes/multi_lora/base.yaml

Lines changed: 0 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -248,40 +248,9 @@ cluster:
248248
num_nodes: 1
249249
multi_lora:
250250
enabled: true
251-
schedule: round_robin
252-
global_batch_size: 64
253251
batch_size_per_adapter: 16
254-
storage_device: cuda
255-
execution_mode: concurrent
256252
adapters:
257253
- name: adapter_a
258-
pin: auto
259-
lora_cfg:
260-
enabled: true
261-
dim: 64
262-
alpha: 128
263-
match_all_linear: false
264-
target_modules:
265-
- '*q_proj'
266-
- '*k_proj'
267-
- '*v_proj'
268-
- '*o_proj'
269-
- '*in_proj'
270-
- '*out_proj'
271-
- '*up_proj'
272-
- '*down_proj'
273-
dropout: 0.0
274-
optimizer:
275-
name: torch.optim.AdamW
276-
kwargs:
277-
lr: 0.0005
278-
weight_decay: 0.01
279-
betas:
280-
- 0.9
281-
- 0.98
282-
eps: 1.0e-05
283-
foreach: false
284-
fused: true
285254
data:
286255
train:
287256
dataset_name: openai_format
@@ -294,33 +263,6 @@ multi_lora:
294263
chat_key: messages
295264
use_preserving_dataset: false
296265
- name: adapter_b
297-
pin: auto
298-
lora_cfg:
299-
enabled: true
300-
dim: 64
301-
alpha: 128
302-
match_all_linear: false
303-
target_modules:
304-
- '*q_proj'
305-
- '*k_proj'
306-
- '*v_proj'
307-
- '*o_proj'
308-
- '*in_proj'
309-
- '*out_proj'
310-
- '*up_proj'
311-
- '*down_proj'
312-
dropout: 0.0
313-
optimizer:
314-
name: torch.optim.AdamW
315-
kwargs:
316-
lr: 0.0005
317-
weight_decay: 0.01
318-
betas:
319-
- 0.9
320-
- 0.98
321-
eps: 1.0e-05
322-
foreach: false
323-
fused: true
324266
data:
325267
train:
326268
dataset_name: openai_format
@@ -333,33 +275,6 @@ multi_lora:
333275
chat_key: messages
334276
use_preserving_dataset: false
335277
- name: adapter_c
336-
pin: auto
337-
lora_cfg:
338-
enabled: true
339-
dim: 64
340-
alpha: 128
341-
match_all_linear: false
342-
target_modules:
343-
- '*q_proj'
344-
- '*k_proj'
345-
- '*v_proj'
346-
- '*o_proj'
347-
- '*in_proj'
348-
- '*out_proj'
349-
- '*up_proj'
350-
- '*down_proj'
351-
dropout: 0.0
352-
optimizer:
353-
name: torch.optim.AdamW
354-
kwargs:
355-
lr: 0.0005
356-
weight_decay: 0.01
357-
betas:
358-
- 0.9
359-
- 0.98
360-
eps: 1.0e-05
361-
foreach: false
362-
fused: true
363278
data:
364279
train:
365280
dataset_name: openai_format
@@ -372,33 +287,6 @@ multi_lora:
372287
chat_key: messages
373288
use_preserving_dataset: false
374289
- name: adapter_d
375-
pin: auto
376-
lora_cfg:
377-
enabled: true
378-
dim: 64
379-
alpha: 128
380-
match_all_linear: false
381-
target_modules:
382-
- '*q_proj'
383-
- '*k_proj'
384-
- '*v_proj'
385-
- '*o_proj'
386-
- '*in_proj'
387-
- '*out_proj'
388-
- '*up_proj'
389-
- '*down_proj'
390-
dropout: 0.0
391-
optimizer:
392-
name: torch.optim.AdamW
393-
kwargs:
394-
lr: 0.0005
395-
weight_decay: 0.01
396-
betas:
397-
- 0.9
398-
- 0.98
399-
eps: 1.0e-05
400-
foreach: false
401-
fused: true
402290
data:
403291
train:
404292
dataset_name: openai_format

examples/configs/recipes/multi_lora/sft_8gpu_native.slurm

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ unset PYTORCH_CUDA_ALLOC_CONF || true
110110
# modules (env-var names intentionally unchanged during vendoring). ---
111111
export NVTE_DISABLE_TRITON_KERNELS=1
112112
export TRITON_CACHE_AUTOTUNING=1
113-
export NOUSNET_DETERMINISTIC=1
114113
export NOUSNET_DETERMINISTIC_SEED=42
115114
export CUBLAS_WORKSPACE_CONFIG=:4096:8
116115
export NOUSNET_DIAG_ENABLED=\${NOUSNET_DIAG_ENABLED:-0}
@@ -126,15 +125,9 @@ export NOUSNET_INIT_IMPORT_SLOT=\${NOUSNET_INIT_IMPORT_SLOT:-}
126125
export PYTHONHASHSEED=\${PYTHONHASHSEED:-0}
127126
export NCCL_ALGO=Ring
128127
export NCCL_DETERMINISTIC=1
129-
export NOUSNET_FUSED_GRAD_CLIP=\${NOUSNET_FUSED_GRAD_CLIP:-0}
130128
export NOUSNET_PER_ADAPTER_GRAD_CLIP=\${NOUSNET_PER_ADAPTER_GRAD_CLIP:-0}
131-
export NOUSNET_TRITON_GRAD_CLIP=\${NOUSNET_TRITON_GRAD_CLIP:-0}
132-
export NOUSNET_MULTI_LORA_LOSS_TRITON=\${NOUSNET_MULTI_LORA_LOSS_TRITON:-0}
133-
export NOUSNET_FORCE_PAD_TO=\${NOUSNET_FORCE_PAD_TO:-1024}
134-
export NOUSNET_FORCE_UNIFORM_ROUTER=\"\${NOUSNET_FORCE_UNIFORM_ROUTER:-1}\"
135129
export TORCH_NCCL_HEARTBEAT_TIMEOUT_SEC=7200
136130
export TORCH_NCCL_BLOCKING_WAIT=0
137-
export NOUSNET_PAD_TOKEN_ID=0
138131
export RAY_DEDUP_LOGS=0
139132
export NOUSNET_RUN_DIR=${EXP_DIR}
140133
# Driver-side imports resolve from the native worktree (the NeMo-RL fork under

examples/run_sft_multi_lora.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
batch_size_per_adapter: 16
1414
adapters:
1515
- name: adapter_a
16-
lora_cfg: {...}
1716
data: {train: {data_path: ...}, validation: {data_path: ...}}
1817
- ...
1918
@@ -22,7 +21,7 @@
2221
2322
Env knobs (kept verbatim from the equivalence campaign so artifacts stay
2423
comparable): NOUSNET_DIAG_ENABLED, NOUSNET_DIAG_LOSS_TRACE,
25-
NOUSNET_DETERMINISTIC_SEED, NOUSNET_INIT_IMPORT_DIR, NOUSNET_INIT_SLOT,
24+
NOUSNET_DETERMINISTIC_SEED, NOUSNET_INIT_IMPORT_DIR, NOUSNET_INIT_IMPORT_SLOT,
2625
NOUSNET_PER_ADAPTER_GRAD_CLIP.
2726
"""
2827

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,23 @@
1-
"""Multi-LoRA adapter and config dataclasses.
2-
3-
See docs/multi-lora-implementation-plan.md §1.2. These are plain, frozen
4-
dataclasses — no NeMo-RL or torch imports here so they stay cheap to load.
5-
"""
1+
"""Configuration consumed by the packed multi-adapter SFT path."""
62

73
from __future__ import annotations
84

95
from dataclasses import dataclass, field
10-
from typing import Literal
116

127

138
@dataclass(frozen=True)
149
class MultiLoRAAdapter:
1510
"""A single LoRA adapter slot in a multi-adapter run."""
1611

1712
name: str
18-
lora_cfg: dict # NeMo-RL lora_cfg block, verbatim
19-
optimizer: dict # NeMo-RL optimizer block, verbatim
20-
data: dict # NeMo-RL data block, verbatim
21-
weight: float = 1.0
22-
nemo_gym: str | None = None # reserved for Phase 3 (RL)
23-
pin: Literal["gpu", "cpu", "auto"] = "auto"
13+
data: dict
2414

2515

2616
@dataclass(frozen=True)
2717
class MultiLoRAConfig:
28-
"""Top-level multi-LoRA config block."""
18+
"""The fields that the native concurrent SFT implementation reads."""
2919

3020
enabled: bool
31-
schedule: Literal["round_robin", "weighted", "progress_aware"] = "round_robin"
32-
global_batch_size: int = 32
33-
# Number of consecutive steps the trainer should stay on a single adapter
34-
# (or group, in concurrent mode) before re-querying the scheduler. Reduces
35-
# weight-swap pressure (sequential mode) or group churn (concurrent mode).
36-
# K=1 (default) = re-query every step.
37-
steps_per_adapter: int = 1
38-
# Where inactive-adapter state lives. "cpu" offloads (saves GPU memory,
39-
# adds a copy per swap); "cuda" keeps every adapter resident on GPU
40-
# (zero swap latency, ~tens of MB per adapter at rank=16). Default
41-
# "cpu" stays safe for big models / many adapters.
42-
storage_device: Literal["cpu", "cuda"] = "cpu"
43-
# Execution mode. "sequential" (default) = Phase A weight-swap loop. "concurrent"
44-
# = Phase B token-packed forward (one base pass serves all GPU-pinned adapters).
45-
execution_mode: Literal["sequential", "concurrent"] = "sequential"
46-
# HBM budget for the memory planner (concurrent mode only). ``None`` = auto-detect
47-
# from torch.cuda.mem_get_info at runtime.
48-
hbm_budget_gb: float | None = None
49-
# Per-adapter micro batch size for the NeMo-RL multi-adapter SFT path
50-
# (round-robin packer in :mod:`nemo_rl.models.multi_lora.data`). The
51-
# global packed batch is ``len(adapters) * batch_size_per_adapter`` rows.
5221
batch_size_per_adapter: int = 1
5322
adapters: list[MultiLoRAAdapter] = field(default_factory=list)
5423

@@ -57,12 +26,6 @@ def from_dict(cls, d: dict) -> "MultiLoRAConfig":
5726
adapters = [MultiLoRAAdapter(**a) for a in d.get("adapters", [])]
5827
return cls(
5928
enabled=d.get("enabled", False),
60-
schedule=d.get("schedule", "round_robin"),
61-
global_batch_size=d.get("global_batch_size", 32),
62-
steps_per_adapter=d.get("steps_per_adapter", 1),
63-
storage_device=d.get("storage_device", "cpu"),
64-
execution_mode=d.get("execution_mode", "sequential"),
65-
hbm_budget_gb=d.get("hbm_budget_gb", None),
6629
batch_size_per_adapter=d.get("batch_size_per_adapter", 1),
6730
adapters=adapters,
6831
)
@@ -73,34 +36,8 @@ def validate(self) -> None:
7336
names = [a.name for a in self.adapters]
7437
if len(names) != len(set(names)):
7538
raise ValueError(f"Duplicate adapter names: {names}")
76-
if self.storage_device not in ("cpu", "cuda"):
77-
raise ValueError(
78-
f"multi_lora.storage_device must be 'cpu' or 'cuda', got "
79-
f"{self.storage_device!r}"
80-
)
81-
if self.steps_per_adapter < 1:
82-
raise ValueError(
83-
f"multi_lora.steps_per_adapter must be >= 1, got "
84-
f"{self.steps_per_adapter}"
85-
)
86-
if self.execution_mode not in ("sequential", "concurrent"):
87-
raise ValueError(
88-
f"multi_lora.execution_mode must be 'sequential' | 'concurrent', "
89-
f"got {self.execution_mode!r}"
90-
)
91-
if self.hbm_budget_gb is not None and self.hbm_budget_gb <= 0:
92-
raise ValueError(
93-
f"multi_lora.hbm_budget_gb must be positive when set, got "
94-
f"{self.hbm_budget_gb}"
95-
)
9639
if self.batch_size_per_adapter < 1:
9740
raise ValueError(
9841
f"multi_lora.batch_size_per_adapter must be >= 1, got "
9942
f"{self.batch_size_per_adapter}"
10043
)
101-
for a in self.adapters:
102-
if a.pin not in ("gpu", "cpu", "auto"):
103-
raise ValueError(
104-
f"adapter {a.name!r} pin must be 'gpu' | 'cpu' | 'auto', "
105-
f"got {a.pin!r}"
106-
)

scripts/submit_parity_battery.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ cd "${REPO_ROOT}"
1616
CANON="${CANON:-${REPO_ROOT}/results/code7x_exactinit_canonical}"
1717
LAUNCHER=examples/configs/recipes/multi_lora/sft_8gpu_native.slurm
1818
CFGDIR=examples/configs/recipes/multi_lora
19-
BASE_ENV="NOUSNET_DIAG_ENABLED=1,NOUSNET_DIAG_LOSS_TRACE=1,NOUSNET_DIAG_TRACE_ONLY=1,NOUSNET_DIAG_LORA_STEP=0,NOUSNET_FORCE_PAD_TO=1024,NOUSNET_INIT_IMPORT_DIR=${CANON}"
19+
BASE_ENV="NOUSNET_DIAG_ENABLED=1,NOUSNET_DIAG_LOSS_TRACE=1,NOUSNET_DIAG_TRACE_ONLY=1,NOUSNET_DIAG_LORA_STEP=0,NOUSNET_INIT_IMPORT_DIR=${CANON}"
2020

2121
if [[ ! -d "${CANON}" ]]; then
2222
cat >&2 <<EOF

0 commit comments

Comments
 (0)