#!/usr/bin/env python3 """ BC-250 GGUF Load Test - isolated from ComfyUI Loads z_image_turbo GGUF and times each step. """ import os, sys, time os.environ["HSA_OVERRIDE_GFX_VERSION"] = "10.1.0" os.environ["HSA_ENABLE_SDMA"] = "0" os.environ["HIP_VISIBLE_DEVICES"] = "0" print("[TEST] Starting GGUF load test...", flush=True) t0 = time.time() import torch print(f"[TEST] torch imported in {time.time()-t0:.1f}s", flush=True) # Add ComfyUI paths sys.path.insert(0, "/home/fabian/ComfyUI") sys.path.insert(0, "/home/fabian/ComfyUI/custom_nodes/ComfyUI-GGUF") t1 = time.time() import gguf print(f"[TEST] gguf imported in {time.time()-t1:.1f}s", flush=True) GGUF_PATH = "/home/fabian/ComfyUI/models/unet/z_image_turbo-Q5_K_S.gguf" # Step 1: Open and read the file print(f"\n[TEST] Step 1: Reading GGUF file...", flush=True) t2 = time.time() reader = gguf.GGUFReader(GGUF_PATH) print(f"[TEST] Reader created in {time.time()-t2:.1f}s", flush=True) print(f"[TEST] Tensors: {len(reader.tensors)}", flush=True) # Check architecture arch = None field = reader.get_field("general.architecture") if field: arch = str(field.parts[field.data[-1]], "utf-8") print(f"[TEST] Architecture: {arch}", flush=True) # Step 2: List first few tensors with types print(f"\n[TEST] Step 2: Tensor info (first 10)...", flush=True) qtype_counts = {} for i, tensor in enumerate(reader.tensors): ttype = tensor.tensor_type tname = getattr(ttype, 'name', repr(ttype)) qtype_counts[tname] = qtype_counts.get(tname, 0) + 1 if i < 10: print(f" {tensor.name}: type={tname} shape={list(reversed(tensor.shape))} size={tensor.data.nbytes}", flush=True) print(f"\n[TEST] Quant type distribution:", flush=True) for k, v in sorted(qtype_counts.items()): print(f" {k}: {v}", flush=True) # Step 3: Try loading one tensor to CPU print(f"\n[TEST] Step 3: Load first Q5_K tensor to CPU...", flush=True) import warnings from dequant import dequantize_tensor, is_quantized for tensor in reader.tensors: if tensor.tensor_type == gguf.GGMLQuantizationType.Q5_K: name = tensor.name print(f" Tensor: {name}", flush=True) print(f" Raw shape: {list(reversed(tensor.shape))}", flush=True) print(f" Raw bytes: {tensor.data.nbytes}", flush=True) t3 = time.time() with warnings.catch_warnings(): warnings.filterwarnings("ignore", message="The given NumPy array is not writable") torch_tensor = torch.from_numpy(tensor.data) # Try to get orig shape field_key = f"comfy.gguf.orig_shape.{name}" field = reader.get_field(field_key) if field: shape = torch.Size(tuple(int(field.parts[part_idx][0]) for part_idx in field.data)) else: shape = torch.Size(tuple(int(v) for v in reversed(tensor.shape))) print(f" Original shape: {shape}", flush=True) print(f" Tensor dtype: {torch_tensor.dtype}, device: {torch_tensor.device}", flush=True) # Create a GGMLTensor-like wrapper torch_tensor.tensor_type = tensor.tensor_type torch_tensor.tensor_shape = shape torch_tensor.patches = [] # Dequantize on CPU print(f" Dequantizing on CPU...", flush=True) t4 = time.time() result = dequantize_tensor(torch_tensor, dtype=torch.float16) dt = time.time() - t4 print(f" Dequantized in {dt:.3f}s -> shape={result.shape} dtype={result.dtype}", flush=True) # Try moving to GPU print(f" Moving to GPU...", flush=True) t5 = time.time() gpu_result = result.to("cuda:0") torch.cuda.synchronize() dt2 = time.time() - t5 print(f" GPU transfer in {dt2:.3f}s", flush=True) print(f" GPU tensor: shape={gpu_result.shape} dtype={gpu_result.dtype} device={gpu_result.device}", flush=True) del gpu_result, result, torch_tensor torch.cuda.empty_cache() break # Step 4: Try dequantizing ALL tensors on CPU print(f"\n[TEST] Step 4: Dequantize all Q5_K tensors on CPU...", flush=True) t_all = time.time() count = 0 for tensor in reader.tensors: if tensor.tensor_type == gguf.GGMLQuantizationType.Q5_K: with warnings.catch_warnings(): warnings.filterwarnings("ignore", message="The given NumPy array is not writable") tt = torch.from_numpy(tensor.data) field_key = f"comfy.gguf.orig_shape.{tensor.name}" field = reader.get_field(field_key) if field: shape = torch.Size(tuple(int(field.parts[part_idx][0]) for part_idx in field.data)) else: shape = torch.Size(tuple(int(v) for v in reversed(tensor.shape))) tt.tensor_type = tensor.tensor_type tt.tensor_shape = shape tt.patches = [] result = dequantize_tensor(tt, dtype=torch.float16) count += 1 if count % 20 == 0: print(f" Dequantized {count} tensors ({time.time()-t_all:.1f}s)...", flush=True) dt_all = time.time() - t_all print(f"\n[TEST] Dequantized {count} Q5_K tensors in {dt_all:.1f}s total", flush=True) print(f"[TEST] Average: {dt_all/max(count,1):.3f}s per tensor", flush=True) print(f"\n[TEST] ALL DONE in {time.time()-t0:.1f}s", flush=True) os._exit(0)