Instructions to use XXXpilar/Fastfill-test with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use XXXpilar/Fastfill-test with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
File size: 5,555 Bytes
e6f80f3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | """Real Accelerator/Gloo entry-point tests with empty ranks and windows."""
from copy import deepcopy
from datetime import timedelta
import json
import os
from pathlib import Path
import sys
import pytest
import torch
from fastfill.v2.tests.test_active_objective_training import _row, _yaw_config
def _worker(rank, rendezvous, directory, mode):
from torch import distributed as dist
from fastfill.v2 import train
os.environ.update(RANK=str(rank), WORLD_SIZE="2", LOCAL_RANK=str(rank), LOCAL_WORLD_SIZE="2",
OMP_NUM_THREADS="1", MASTER_ADDR="127.0.0.1", MASTER_PORT="29513")
dist.init_process_group("gloo", init_method=rendezvous, rank=rank, world_size=2,
timeout=timedelta(seconds=20))
patches = pytest.MonkeyPatch()
try:
if sys.platform == "darwin":
# torch 2.13 barrier(device_ids=[...]) chooses the available MPS
# accelerator even for a CPU/Gloo group. This CPU test explicitly
# selects CPU discovery; collectives/backward remain real Gloo.
patches.setattr(torch._C, "_get_accelerator", lambda: torch.device("cpu"))
root = Path(directory)
rows_count = {"peer_empty": 2, "last_empty": 4, "empty_then_valid": 8, "all_empty": 4}[mode]
data = root / "train.jsonl"
if rank == 0:
data.write_text("".join(json.dumps(_row(str(i))) + "\n" for i in range(rows_count)))
dist.barrier()
original_collate, original_preflight, original_loader = train.collate_samples, train._preflight, train.DataLoader
state = {"after_preflight": False}
def collate(rows, *args, **kwargs):
batch = original_collate(rows, *args, **kwargs)
if state["after_preflight"]:
yaw = batch["validity"]["yaw"].clone()
for i, row in enumerate(rows):
identity = int(row["provenance"]["scene_id"])
empty = (mode == "all_empty" or (mode == "peer_empty" and rank == 0)
or (mode == "last_empty" and identity >= 2)
or (mode == "empty_then_valid" and identity < 4))
if empty:
yaw[i] = False
batch = {**batch, "validity": {**batch["validity"], "yaw": yaw}}
return batch
def preflight(*args, **kwargs):
state["after_preflight"] = False
result = original_preflight(*args, **kwargs)
state["after_preflight"] = True
return result
def loader(rows, **kwargs):
return original_loader(rows, **{**kwargs, "shuffle": False})
models, before = [], []
original_build = train.build_model
def build(config):
model = original_build(config)
models.append(model)
before.append(deepcopy(model.state_dict()))
return model
patches.setattr(train, "collate_samples", collate)
patches.setattr(train, "_preflight", preflight)
patches.setattr(train, "DataLoader", loader)
patches.setattr(train, "build_model", build)
config = _yaw_config()
config["training"]["gradient_accumulation_steps"] = 1 if mode == "peer_empty" else 2
if mode == "all_empty":
with pytest.raises(RuntimeError, match="no active objective"):
train.run_training(config, data, root / "run")
changed = sum(not torch.equal(before[0][name], value) for name, value in models[0].state_dict().items())
assert changed == 0
observation = {"optimizer_updates": 0, "changed_parameter_tensors": changed}
else:
logs = train.run_training(config, data, root / "run")
assert len(logs) == 1 and logs[0]["step"] == 1
assert logs[0]["active_objective_count"] == {"peer_empty": 1, "last_empty": 2, "empty_then_valid": 4}[mode]
assert logs[0]["gradient_norms"]["yaw_logits_head"] > 0
changed = sum(not torch.equal(before[0][name], value) for name, value in models[0].state_dict().items())
assert changed > 0
observation = {"optimizer_updates": 1, "active_objective_count": logs[0]["active_objective_count"],
"changed_parameter_tensors": changed}
if rank == 0:
manifest = json.loads((root / "run/run_manifest.json").read_text())
assert manifest["world_size"] == 2
assert manifest["skipped_no_objective_windows"] == int(mode == "empty_then_valid")
(root / f"rank-{rank}.json").write_text(json.dumps(observation, indent=2) + "\n")
finally:
patches.undo()
if dist.is_initialized():
dist.destroy_process_group()
@pytest.mark.skipif(not torch.distributed.is_available() or not torch.distributed.is_gloo_available(), reason="requires Gloo")
@pytest.mark.parametrize("mode", ["peer_empty", "last_empty", "empty_then_valid", "all_empty"])
def test_actual_two_rank_objective_windows(tmp_path, monkeypatch, mode):
monkeypatch.setenv("GLOO_SOCKET_IFNAME", "lo0" if sys.platform == "darwin" else "lo")
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "") # CPU Gloo ranks: with one visible GPU, rank 1 would ask for cuda:1
torch.multiprocessing.spawn(_worker, args=("file://" + str(tmp_path / "rendezvous"), str(tmp_path), mode),
nprocs=2, join=True)
assert all((tmp_path / f"rank-{rank}.json").exists() for rank in range(2))
|