# Alignment Profiling Log

Setup: da3L-2v-N64 checkpoint, 3 scenes, 252px, 3 target views.

## Run 1: B=1 baseline

| Variant           | PSNR  | LPIPS  | Time(ms) | Speedup |
|-------------------|-------|--------|----------|---------|
| no_align          | 19.53 | 0.2287 | 252      | —       |
| accurate_200      | 24.40 | 0.1684 | 1287     | 0.12x   |
| **baseline_30**   | 24.21 | 0.1704 | 151      | **1.0x**|
| pruned10_30       | 24.18 | 0.1705 | 111      | 1.36x   |
| halfres_30        | 23.91 | 0.1721 | 129      | 1.17x   |
| quarterres_30     | 21.31 | 0.1940 | 195      | 0.77x   |

---

## Run 2: B=8 pruning coarse sweep

| Variant      | #Gauss | Wall(ms) | Speedup | PSNR  | dPSNR vs accurate |
|--------------|--------|----------|---------|-------|-------------------|
| baseline_30  | 41472  | 911      | 1.0x    | 24.21 | -0.19             |
| pruned10_30  | 19820  | 588      | 1.55x   | 24.18 | -0.22             |
| pruned30_30  | 8054   | 472      | 1.93x   | 23.89 | -0.51             |
| pruned50_30  | 3362   | 443      | 2.06x   | 23.13 | -1.27             |
| pruned70_30  | 1007   | 426      | 2.14x   | 20.17 | -4.23             |

---

## Run 3: B=8 fine-grained pruning sweep (0–0.3)

Golden standard: **accurate_200** = 24.40 PSNR, 0.1684 LPIPS

| Variant      | #Gauss | %pruned | Wall(ms) | Speedup | PSNR  | dPSNR vs gold | LPIPS  | dLPIPS vs gold |
|--------------|--------|---------|----------|---------|-------|---------------|--------|----------------|
| accurate_200 | 41472  | 0%      | 9687     | 0.09x   | 24.40 | 0             | 0.1684 | 0              |
| baseline_30  | 41472  | 0%      | 891      | 1.00x   | 24.21 | -0.19         | 0.1704 | +0.0020        |
| pruned01_30  | 36580  | 12%     | 826      | 1.08x   | 24.21 | -0.19         | 0.1704 | +0.0020        |
| pruned05_30  | 26451  | 36%     | 674      | 1.32x   | 24.20 | -0.20         | 0.1704 | +0.0020        |
| pruned10_30  | 19820  | 52%     | 570      | 1.56x   | 24.18 | -0.22         | 0.1705 | +0.0021        |
| pruned15_30  | 15407  | 63%     | 523      | 1.70x   | 24.14 | -0.26         | 0.1711 | +0.0027        |
| pruned20_30  | 12316  | 70%     | 498      | 1.79x   | 24.10 | -0.30         | 0.1715 | +0.0031        |
| pruned25_30  | 9893   | 76%     | 472      | 1.89x   | 24.03 | -0.37         | 0.1720 | +0.0036        |
| pruned30_30  | 8054   | 81%     | 461      | 1.93x   | 23.89 | -0.51         | 0.1738 | +0.0054        |

### Per-Step Timing (ms/step avg)

| Variant      | #Gauss | Render | Loss | Backward | Total/step |
|--------------|--------|--------|------|----------|------------|
| baseline_30  | 41472  | 9.79   | 0.16 | 14.70    | 25.03      |
| pruned05_30  | 26451  | 7.04   | 0.14 | 10.48    | 18.01      |
| pruned10_30  | 19820  | 6.12   | 0.14 | 8.00     | 14.60      |
| pruned15_30  | 15407  | 5.80   | 0.13 | 6.80     | 13.07      |
| pruned20_30  | 12316  | 5.70   | 0.13 | 6.06     | 12.23      |
| pruned25_30  | 9893   | 5.57   | 0.13 | 5.36     | 11.38      |
| pruned30_30  | 8054   | 5.53   | 0.13 | 5.01     | 10.98      |

### Analysis

- **Backward dominates**: 15ms (full) vs 10ms (render). Loss is negligible (0.15ms).
- **Render floor ~5.5ms**: batch loop overhead (8 iters) + kernel launch. Can't go lower.
- **Backward scales linearly**: 15ms (41k) → 5ms (8k). Floor ~3.5ms.

**Sweet spots for training:**
- **pruned10 (opacity > 0.1)**: 1.56x speed, only -0.03 PSNR vs baseline / -0.22 vs gold. Safest.
- **pruned20 (opacity > 0.2)**: 1.79x speed, -0.11 PSNR vs baseline / -0.30 vs gold. Good tradeoff.
- **pruned30 (opacity > 0.3)**: 1.93x speed but -0.51 PSNR vs gold. Quality starts to degrade.

Note: dPSNR at alignment stage overstates training impact — training only needs
"good enough" alignment for clean gradients, not pixel-perfect rendering.

### Estimated training time impact (B=16/GPU, 30 steps)

| Config      | Align overhead/step | Total ETA (from 2.2d base) |
|-------------|--------------------|-----------------------------|
| No align    | 0                  | 2.2 days                    |
| baseline_30 | ~1.8s              | 6.2 days (observed)         |
| pruned10_30 | ~1.0s              | ~4.2 days                   |
| pruned20_30 | ~0.9s              | ~3.8 days                   |

---

## Run 4: Second-order methods (LM, line search)

All with opacity pruning 0.2, B=8. Checkpoint: da3L-sm-uniform-2v-N32.

| Variant | Method | PSNR | Time(ms) | Notes |
|---------|--------|------|----------|-------|
| baseline_30 | AdamW 6-DoF | 24.10 | 495 | reference |
| ls3_8p | 3 grad + 8 probes | 20.97 | 149 | line search, 1D of 6D |
| lm5 | LM 5 steps | 23.17 | 193 | finite-diff J, ~37ms/step |
| lm10 | LM 10 steps | 24.06 | 377 | near baseline quality |
| lm15 | LM 15 steps | 24.21 | 568 | matches baseline, slower |
| mse_30 | AdamW MSE loss | 24.02 | ~500 | L1 slightly better |

**Conclusion**: LM can't beat first-order. Each LM step needs 7 renders (1 base + 6 perturbations) for finite-diff Jacobian = ~37ms/step vs ~12ms/step for AdamW. Without analytical Jacobians, second-order is uncompetitive.

---

## Run 5: Scale-only alignment

Hypothesis: main misalignment is global scale between predicted Gaussians and GT coordinate frame.
Single scalar `s` per scene, applied as `init_pose.scale_translation(s)`.

### Scale convergence

| Steps | PSNR | Time(ms) |
|-------|------|----------|
| 0 (no_align) | 20.69 | — |
| 1 | 20.93 | 11 |
| 2 | 21.15 | 5 |
| 3 | 21.33 | 7 |
| 5 | 21.64 | 11 |
| 10 | 21.83 | 28 |
| 20 | 21.91 | 57 |
| 30 | 21.89 | 79 |

Learned scales: s ∈ [0.96, 1.10] across scenes. Converges by ~5 steps.
Scale-only recovers +1.2 PSNR out of +2.6 total alignment gain (~45%).

### Scale + 6-DoF combos vs pure 6-DoF

| Config | Total steps | PSNR | Time(ms) | vs matched pure 6-DoF |
|--------|-------------|------|----------|------------------------|
| baseline_30 | 30 6dof | 23.33 | 115 | — |
| s5_r25 | 5s+25r | 23.31 | 90 | -0.02, 22% faster |
| r20 | 20 6dof | 23.31 | 69 | — |
| s5_r15 | 5s+15r | 23.19 | 57 | -0.12, 17% faster |
| r15 | 15 6dof | 23.01 | 48 | — |
| s3_r12 | 3s+12r | 22.86 | 45 | -0.15, 6% faster |
| r10 | 10 6dof | 22.72 | 34 | — |
| s3_r7 | 3s+7r | 22.77 | 25 | +0.05, 26% faster |

**Conclusion**: Scale init gives marginal benefit — 6-DoF optimizer handles scale implicitly. Main value at low step budgets. Reducing total steps is the simplest win: r15 at 48ms gets 23.01 PSNR.

---

## Run 6: Depth-based Procrustes alignment

Hypothesis: unproject rendered + GT depth to world frame, Procrustes SVD for closed-form R,t init.
Two variants: per-view (camera-frame) and global (world-frame, concat across 3 target views).
IRLS Huber weights (3 iters), depth ratio filter [0.3, 3.0].

| Variant | PSNR | Time(ms) | dr(°) | dt(m) |
|---------|------|----------|-------|-------|
| no_align | 19.53 | — | — | — |
| baseline_30 | 24.10 | 112 | 0.23 | 0.021 |
| depth_pv | 16.06 | 17 | 1.64 | 0.046 |
| depth_gbl | 17.07 | 3 | 1.44 | 0.080 |
| depth_gbl_r20 | 20.65 | 74 | 0.85 | 0.059 |
| depth_pv_r20 | 19.90 | 74 | 1.24 | 0.058 |

**Conclusion**: Not viable. Depth noise (rendered Gaussians + pseudo-GT monocular depth) overwhelms the small actual misalignment (~0.2°, 0.02m). Procrustes finds 6x too large corrections in wrong direction. Even as initializer for gradient refinement, it hurts vs vanilla gradient-only.

---

## Run 7: Final comparison (gpp-N32, 20 scenes, B=8, 252px)

Checkpoint: gpp-N32 (DA3-Large, 2v, GPP=32). 20 scenes for statistical reliability.

| Config | #Gauss | PSNR | dPSNR vs gold | ms/step | Wall(ms) | Speedup vs r30_noprune |
|---|---|---|---|---|---|---|
| accurate_200 | 20736 | **23.14** | — | — | 10277 | — |
| **r30_noprune** (current) | 20736 | 22.95 | -0.19 | **17.3** | **653** | **1.0x** |
| baseline_30 (pruned20) | 7299 | 22.91 | -0.23 | 11.6 | 479 | 1.36x |
| r20 (pruned20) | 7299 | 22.73 | -0.41 | 11.6 | 363 | 1.80x |
| **r15 (pruned20)** | 7299 | **22.60** | -0.54 | 11.6 | **240** | **2.72x** |
| r10_noprune | 20736 | 22.24 | -0.90 | 17.3 | 241 | 2.71x |
| r10 (pruned20) | 7299 | 22.21 | -0.93 | 11.6 | 182 | 3.59x |

### Per-step breakdown (ms)

| Config | #Gauss | Render | Backward | Overhead | Total/step |
|---|---|---|---|---|---|
| r30_noprune | 20736 | 7.25 | 9.62 | 0.42 | 17.3 |
| baseline_30 (pruned20) | 7299 | 5.60 | 5.60 | 0.41 | 11.6 |

Pruning at 0.2 cuts Gaussians 65% (20.7k → 7.3k), per-step 1.49x faster. Quality loss: -0.04 PSNR.

---

## Overall Conclusions

**Pruning is the bigger win than step reduction.** Opacity>0.2 pruning gives 1.49x per-step speedup with negligible quality loss. Step reduction gives linear wall-time savings.

| Optimization | vs r30_noprune (current) | PSNR cost |
|---|---|---|
| Add pruning 0.2 (30 steps) | 1.36x | -0.04 |
| Add pruning 0.2 + reduce to 15 steps | **2.72x** | -0.35 |
| Add pruning 0.2 + reduce to 10 steps | 3.59x | -0.74 |

**Recommendation**: pruned20 + 15 steps. 2.72x faster alignment (~240ms vs 653ms at B=8), -0.35 PSNR at eval. Training quality impact should be smaller since alignment only needs "good enough" for clean gradients.

**Dead ends**: LM/Gauss-Newton (7 renders/step), line search (1D of 6D), scale init (marginal), depth Procrustes (noise dominates), half-res rendering (quality drops too fast), torch.compile (gsplat dominates, <5% gain).
