Download tests/diagnose_xpu_leak.py from DRDMsig/Omini3D: direct link, hf CLI and curl.
- Browser
- Download file 8.76 kB
-
https://huggingface.co/DRDMsig/Omini3D/resolve/main/tests/diagnose_xpu_leak.py
- Command line
-
hf download hf://DRDMsig/Omini3D/tests/diagnose_xpu_leak.py
-
curl -L -o diagnose_xpu_leak.py https://huggingface.co/DRDMsig/Omini3D/resolve/main/tests/diagnose_xpu_leak.py
8.76 kB
| """Diagnose XPU memory leak by testing each component in isolation. | |
| Run on a single XPU tile (no SLURM needed): | |
| python tests/diagnose_xpu_leak.py | |
| Tests each component for 20 iterations, reporting device_free after each. | |
| A decreasing device_free indicates a leak in that component. | |
| """ | |
| import os, sys, gc | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| import torch | |
| import torch.nn.functional as F | |
| import torch.distributed as dist | |
| from torch.nn.parallel import DistributedDataParallel as DDP | |
| try: | |
| import intel_extension_for_pytorch as ipex | |
| except ImportError: | |
| pass | |
| DEVICE = "xpu:0" if hasattr(torch, "xpu") and torch.xpu.device_count() > 0 else "cuda:0" | |
| IMG_SIZE = 128 | |
| BATCH = 2 | |
| NDIMS = 3 | |
| TIMESTEPS = 80 | |
| STEPS = 20 | |
| def get_device_free(): | |
| if "xpu" in DEVICE: | |
| torch.xpu.synchronize() | |
| free, total = torch.xpu.mem_get_info(0) | |
| return free / 1024**3 | |
| else: | |
| torch.cuda.synchronize() | |
| free, total = torch.cuda.mem_get_info(0) | |
| return free / 1024**3 | |
| def empty_cache(): | |
| gc.collect() | |
| if "xpu" in DEVICE: | |
| torch.xpu.synchronize() | |
| torch.xpu.empty_cache() | |
| else: | |
| torch.cuda.synchronize() | |
| torch.cuda.empty_cache() | |
| def test_network_forward_only(): | |
| """Test: network forward pass without backward or DDP.""" | |
| from Diffusion.networks import get_net | |
| Net = get_net("om_net") | |
| net = Net(n_steps=TIMESTEPS, ndims=NDIMS, num_input_chn=1, res=IMG_SIZE).to(DEVICE) | |
| net.eval() | |
| empty_cache() | |
| print(f"\n{'='*60}") | |
| print("TEST 1: Network forward only (no backward, no DDP)") | |
| print(f"{'='*60}") | |
| base = get_device_free() | |
| print(f" Baseline: {base:.2f} GiB free") | |
| for step in range(STEPS): | |
| x = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| y = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| t = torch.randint(0, TIMESTEPS, (BATCH,), device=DEVICE) | |
| with torch.no_grad(): | |
| out = net(x=x, y=y, t=t, rec_num=2) | |
| del x, y, t, out | |
| empty_cache() | |
| free = get_device_free() | |
| print(f" Step {step:2d}: {free:.2f} GiB free (delta: {free - base:+.3f})") | |
| del net | |
| empty_cache() | |
| def test_network_backward_only(): | |
| """Test: network forward + backward WITHOUT optimizer.step().""" | |
| from Diffusion.networks import get_net | |
| Net = get_net("om_net") | |
| net = Net(n_steps=TIMESTEPS, ndims=NDIMS, num_input_chn=1, res=IMG_SIZE).to(DEVICE) | |
| net.train() | |
| empty_cache() | |
| print(f"\n{'='*60}") | |
| print("TEST 2a: Network forward + backward ONLY (no optimizer.step)") | |
| print(f"{'='*60}") | |
| base = get_device_free() | |
| print(f" Baseline: {base:.2f} GiB free") | |
| for step in range(STEPS): | |
| x = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| y = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| t = torch.randint(0, TIMESTEPS, (BATCH,), device=DEVICE) | |
| out = net(x=x, y=y, t=t, rec_num=2) | |
| loss = out.mean() | |
| net.zero_grad() | |
| loss.backward() | |
| del x, y, t, out, loss | |
| empty_cache() | |
| free = get_device_free() | |
| print(f" Step {step:2d}: {free:.2f} GiB free (delta: {free - base:+.3f})") | |
| del net | |
| empty_cache() | |
| def test_network_forward_backward(): | |
| """Test: network forward + backward with optimizer.step().""" | |
| from Diffusion.networks import get_net | |
| Net = get_net("om_net") | |
| net = Net(n_steps=TIMESTEPS, ndims=NDIMS, num_input_chn=1, res=IMG_SIZE).to(DEVICE) | |
| net.train() | |
| optimizer = torch.optim.Adam(net.parameters(), lr=1e-5) | |
| empty_cache() | |
| print(f"\n{'='*60}") | |
| print("TEST 2: Network forward + backward (no DDP)") | |
| print(f"{'='*60}") | |
| base = get_device_free() | |
| print(f" Baseline: {base:.2f} GiB free") | |
| for step in range(STEPS): | |
| x = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| y = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| t = torch.randint(0, TIMESTEPS, (BATCH,), device=DEVICE) | |
| out = net(x=x, y=y, t=t, rec_num=2) | |
| loss = out.mean() | |
| optimizer.zero_grad() | |
| loss.backward() | |
| optimizer.step() | |
| del x, y, t, out, loss | |
| empty_cache() | |
| free = get_device_free() | |
| print(f" Step {step:2d}: {free:.2f} GiB free (delta: {free - base:+.3f})") | |
| del net, optimizer | |
| empty_cache() | |
| def test_deformddpm_forward_backward(): | |
| """Test: full DeformDDPM pipeline (diffuse + recover + backward) without DDP.""" | |
| from Diffusion.diffuser import DeformDDPM | |
| from Diffusion.networks import get_net, STN | |
| Net = get_net("om_net") | |
| network = Net(n_steps=TIMESTEPS, ndims=NDIMS, num_input_chn=1, res=IMG_SIZE) | |
| ddpm = DeformDDPM( | |
| network=network, | |
| n_steps=TIMESTEPS, | |
| image_chw=[1, IMG_SIZE, IMG_SIZE, IMG_SIZE], | |
| device=DEVICE, | |
| batch_size=BATCH, | |
| v_scale=5e-5, | |
| ).to(DEVICE) | |
| ddf_stn = STN(img_sz=IMG_SIZE, ndims=NDIMS, padding_mode="border", device=DEVICE).to(DEVICE) | |
| import Diffusion.losses as losses | |
| loss_reg = losses.Grad(penalty='l2') | |
| loss_ang = losses.MRSE() | |
| optimizer = torch.optim.Adam(ddpm.parameters(), lr=1e-5) | |
| empty_cache() | |
| print(f"\n{'='*60}") | |
| print("TEST 3: DeformDDPM full pipeline (no DDP)") | |
| print(f"{'='*60}") | |
| base = get_device_free() | |
| print(f" Baseline: {base:.2f} GiB free") | |
| for step in range(STEPS): | |
| x0 = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| t = torch.randint(0, TIMESTEPS, (BATCH,), device=DEVICE) | |
| pre_dvf_I, dvf_I = ddpm(img_org=x0, t=t, cond_imgs=None, mask=1, proc_type=[], text=None) | |
| loss_ddf = loss_reg(pre_dvf_I, img=x0) | |
| trm_pred = ddf_stn(pre_dvf_I, dvf_I) | |
| loss_gen_a = loss_ang(pred=trm_pred, inv_lab=dvf_I, ddf_stn=None, mask=1) | |
| loss_tot = 2.0 * loss_gen_a + 4.0 * loss_ddf | |
| optimizer.zero_grad() | |
| loss_tot.backward() | |
| optimizer.step() | |
| del x0, t, pre_dvf_I, dvf_I, trm_pred, loss_ddf, loss_gen_a, loss_tot | |
| empty_cache() | |
| free = get_device_free() | |
| print(f" Step {step:2d}: {free:.2f} GiB free (delta: {free - base:+.3f})") | |
| del ddpm, ddf_stn, optimizer | |
| empty_cache() | |
| def test_ddp_backward(): | |
| """Test: DDP-wrapped network forward + backward (requires init_process_group).""" | |
| # Initialize single-process DDP | |
| os.environ.setdefault("MASTER_ADDR", "localhost") | |
| os.environ.setdefault("MASTER_PORT", "29500") | |
| backend = "ccl" if "xpu" in DEVICE else "nccl" | |
| if not dist.is_initialized(): | |
| dist.init_process_group(backend=backend, rank=0, world_size=1) | |
| from Diffusion.networks import get_net | |
| Net = get_net("om_net") | |
| net = Net(n_steps=TIMESTEPS, ndims=NDIMS, num_input_chn=1, res=IMG_SIZE).to(DEVICE) | |
| net = DDP(net, device_ids=[0], find_unused_parameters=True) | |
| optimizer = torch.optim.Adam(net.parameters(), lr=1e-5) | |
| empty_cache() | |
| print(f"\n{'='*60}") | |
| print("TEST 4: DDP (find_unused_parameters=True) forward + backward") | |
| print(f"{'='*60}") | |
| base = get_device_free() | |
| print(f" Baseline: {base:.2f} GiB free") | |
| for step in range(STEPS): | |
| x = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| y = torch.randn(BATCH, 1, IMG_SIZE, IMG_SIZE, IMG_SIZE, device=DEVICE) | |
| t = torch.randint(0, TIMESTEPS, (BATCH,), device=DEVICE) | |
| out = net(x=x, y=y, t=t, rec_num=2) | |
| loss = out.mean() | |
| optimizer.zero_grad() | |
| loss.backward() | |
| optimizer.step() | |
| del x, y, t, out, loss | |
| empty_cache() | |
| free = get_device_free() | |
| print(f" Step {step:2d}: {free:.2f} GiB free (delta: {free - base:+.3f})") | |
| del net, optimizer | |
| if dist.is_initialized(): | |
| dist.destroy_process_group() | |
| empty_cache() | |
| if __name__ == "__main__": | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--test", type=int, default=0, help="Run specific test (1-4), 0=all") | |
| args = parser.parse_args() | |
| torch.xpu.set_device(0) if "xpu" in DEVICE else None | |
| print(f"Device: {DEVICE}") | |
| print(f"Total memory: {torch.xpu.get_device_properties(0).total_memory / 1024**3:.1f} GiB" if "xpu" in DEVICE else "") | |
| if args.test in (0, 1): | |
| test_network_forward_only() | |
| if args.test in (0, 2): | |
| test_network_backward_only() | |
| if args.test in (0, 3): | |
| test_network_forward_backward() | |
| if args.test in (0, 4): | |
| test_deformddpm_forward_backward() | |
| if args.test in (0, 5): | |
| test_ddp_backward() | |
| print("\nDone. If device_free decreases linearly in any test, that component leaks.") | |