Skip to main content

machin-diffusion-validation

How to validate output correctness after optimizations. Reference comparison, pixel diff methodology, and image quality metrics.

소스 정보

저장소
javimosch/machin-diffusion
최근 소스 활동
2026년 9월 10일 05:44
감지된 SKILL.md 언어
영어
스타
0
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
machin-diffusion-validation
description
How to validate output correctness after optimizations. Reference comparison, pixel diff methodology, and image quality metrics.
# Validation Methodology ## Why validate after every optimization Fused GPU kernels reorder floating-point operations, giving slightly different results. The goal is to confirm the optimization didn't break correctness — not to achieve bit-exact reproduction. ## Reference pipeline The reference is at `/tmp/ref_pipeline.py` (diffusers/PyTorch with the **correct trailing scheduler**). It validates stage-by-stage: | Stage | Metric | Typical value | |-------|--------|--------------| | CLIP embeddings | max diff | ~0.000018 | | UNet noise prediction | max diff | ~0.000307 | | UNet noise prediction | correlation | 1.000000 | | Final latent | max diff | ~0.000070 | | Final latent | correlation | 1.000000 | | Image | mean pixel diff | 0.01–0.05 | | Image | max pixel diff | 1–2 | After fused kernels (group_norm_silu, attention_f32, conv3x3_t4x4, matmul_tiled): - **pixel diff mean=0.02, max=1** — within tolerance, from float reordering in online softmax and tiled accumulation. ## Standard validation prompt ``` "a girl photo, close take" seed: 12345 guidance_scale: 0.0 512x512 trailing scheduler ``` Expected output: photo-like image, ~75% skin-tone pixels, edge strength ~5.0, R mean ~151. ## How to compare images ```python import numpy as np from PIL import Image prev = np.array(Image.open('previous.png'), dtype=np.int16) curr = np.array(Image.open('current.png'), dtype=np.int16) diff = np.abs(curr - prev) print(f'pixel diff mean={diff.mean():.2f} max={diff.max()}') # Acceptable: mean < 0.05, max <= 1 ``` ## Image quality metrics ```python arr = np.array(img) print(f'R: mean={arr[:,:,0].mean():.0f} std={arr[:,:,0].std():.0f}') gray = arr.mean(axis=2).astype(np.float32) gx = np.abs(np.diff(gray, axis=1)) print(f'edge strength: {gx.mean():.1f}') skin = ((arr[:,:,0] > arr[:,:,1]) & (arr[:,:,1] > arr[:,:,2]) & (arr[:,:,0] > 80) & (arr[:,:,0] < 220)).sum() print(f'skin-tone: {100*skin/(w*h):.1f}%') ``` ## Fetching output from Windows ```bash # PPM → base64 → decode locally rcx ordi-jla "certutil -encode output.ppm out.b64 && type out.b64" 60 > /tmp/raw # Then: decode base64, parse PPM header (P6\n<w> <h>\n255\n), load with PIL ``` ## What "correct" looks like - **Abstract noise** → scheduler is wrong (check `timestep_spacing: "trailing"`) - **High-contrast garbage** → CFG was added (check `guidance_scale: 0.0`) - **Photo-like, warm, smooth** → correct - **pixel diff > 0.05 or max > 2** → optimization broke something, investigate ## Don't claim byte-identical After fused kernels, output is numerically equivalent but not bit-identical. Use measured tolerances (mean < 0.05, max ≤ 1) in documentation, not "byte-identical" or "exact". ## SDXL-Lightning validation (2026-09-08) ### Critical finding: CLIP attention must be CAUSAL CLIP text encoders (both TE1 and TE2) use **causal** attention — position i only attends to positions j ≤ i. The SDXL port originally used bidirectional `attention_f32`, which produced TE2 hidden states with only **0.18 correlation** to the diffusers reference. This was the root cause of the abstract noise output. **Fix:** Added `attention_causal_f32` builtin to the machin compiler (OpenCL kernel + CPU fallback). After the fix, TE2 hidden correlation jumped to **0.9993**. ### SDXL reference setup (RunPod) The reference pipeline (`scripts/sdxl_reference.py`) loads components directly: - `CLIPTextModel` (TE1) + `CLIPTextModelWithProjection` (TE2) with `attn_implementation="eager"` - `EulerDiscreteScheduler` with `timestep_spacing="trailing"`, 4 timesteps - `UNet2DConditionModel` loaded from `unet_4step_fp32.safetensors` - `AutoencoderKL` with `scaling_factor=0.13025` **Package compatibility:** torch 2.5.1+cu121, transformers 4.48.3, diffusers 0.40.0, huggingface_hub 1.30.0. Earlier versions had import errors (CLIPImageProcessor removed in transformers 5.x, `get_cached_repo_tree` missing in old hub, SDPA causal mask shape bug). ### Validated stages | Stage | Metric | Value | |-------|--------|-------| | TE2 hidden [77×1280] | correlation | 0.9993 | | TE2 hidden | mean_diff | 0.019 | | Scheduler sigmas | exact | [14.615, 4.082, 1.613, 0.693, 0.0] | | Scheduler timesteps | exact | [999, 749, 499, 249] | | VAE scaling factor | exact | 0.13025 | ### Pending validation (pod terminated, low balance) - UNet step-0 noise prediction - VAE decode output - Pooled output after text_projection - Visual image comparison ### Debug dump format `main_sdxl.src` accepts an optional 4th argument `debug_dir`. When provided, dumps: - `te2_hidden.bin` — [77, 1280] float32 - `te2_pooled_raw.bin` — [1280] float32 (before text_projection) - `vae_output.bin` — [3, 1024, 1024] float32 The reference saves `.npy` files for all stages. Compare with: ```python ref = np.load('/workspace/ref/te2_hidden.npy')[0] # [77, 1280] ours = np.fromfile('/workspace/our/te2_hidden.bin', dtype=np.float32).reshape(77, 1280) corr = np.corrcoef(ref.flatten(), ours.flatten())[0,1] ```
GitHub에서 보기