zk-Armor commited on
Commit
a39b81e
·
verified ·
1 Parent(s): 8a64669

Upload nvfp4/examples/nvfp4_inference.rs with huggingface_hub

Browse files
Files changed (1) hide show
  1. nvfp4/examples/nvfp4_inference.rs +100 -0
nvfp4/examples/nvfp4_inference.rs ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // NVFP4 Inference Example for Candle
2
+ //
3
+ // This example demonstrates:
4
+ // 1. Loading a model from HuggingFace
5
+ // 2. Quantizing weights to NVFP4
6
+ // 3. Running inference with NVFP4 quantized weights on CUDA
7
+ //
8
+ // Usage:
9
+ // cargo run --release --features cuda --bin nvfp4-inference -- \
10
+ // --model igorls/gemma-4-12B-it-heretic-v1 \
11
+ // --prompt "Hello, world!" \
12
+ // --n-tokens 128
13
+
14
+ use candle::{DType, Device, Tensor, Module};
15
+ use std::io::Write;
16
+
17
+ fn main() -> candle::Result<()> {
18
+ let model_id = std::env::args()
19
+ .find(|arg| arg.starts_with("--model="))
20
+ .map(|s| s[8..].to_string())
21
+ .unwrap_or_else(|| "igorls/gemma-4-12B-it-heretic-v1".to_string());
22
+
23
+ let prompt = std::env::args()
24
+ .find(|arg| arg.starts_with("--prompt="))
25
+ .map(|s| s[9..].to_string())
26
+ .unwrap_or_else(|| "What is the meaning of life?".to_string());
27
+
28
+ let n_tokens: usize = std::env::args()
29
+ .find(|arg| arg.starts_with("--n-tokens="))
30
+ .and_then(|s| s[11..].parse().ok())
31
+ .unwrap_or(128);
32
+
33
+ println!("NVFP4 Inference Example");
34
+ println!("Model: {model_id}");
35
+ println!("Prompt: {prompt}");
36
+ println!("Max tokens: {n_tokens}");
37
+ println!();
38
+
39
+ // Initialize CUDA device
40
+ let device = Device::cuda_if_available(0)?;
41
+ println!("Device: {:?}", device);
42
+
43
+ // Test NVFP4 quantization
44
+ println!("\n=== NVFP4 Quantization Test ===");
45
+ let test_data = Tensor::randn(0f32, 1f32, (256, 512), &device)?;
46
+ println!("Input shape: {:?}", test_data.shape());
47
+
48
+ // Quantize to NVFP4
49
+ use candle::quantized::{GgmlDType, QTensor};
50
+ let qtensor = QTensor::quantize(&test_data, GgmlDType::NVFP4)?;
51
+ println!("Quantized dtype: {:?}", qtensor.dtype());
52
+ println!("Quantized shape: {:?}", qtensor.shape());
53
+
54
+ // Dequantize back
55
+ let dequant = qtensor.dequantize(&device)?;
56
+ println!("Dequantized shape: {:?}", dequant.shape());
57
+
58
+ // Compute error
59
+ let diff = test_data.broadcast_sub(&dequant)?;
60
+ let max_err = diff.max_all()?.to_scalar::<f32>()?;
61
+ let mean_err = diff.mean_all()?.to_scalar::<f32>()?;
62
+ let ref_mean = test_data.abs()?.mean_all()?.to_scalar::<f32>()?;
63
+ println!("Max error: {:.6}", max_err);
64
+ println!("Mean error: {:.6}", mean_err);
65
+ println!("Relative error: {:.6}", mean_err / ref_mean);
66
+
67
+ // Test matmul
68
+ println!("\n=== NVFP4 MatMul Test ===");
69
+ let x = Tensor::randn(0f32, 1f32, (1, 512), &device)?;
70
+ let w = Tensor::randn(0f32, 0.5f32, (256, 512), &device)?;
71
+ let w_q = QTensor::quantize(&w, GgmlDType::NVFP4)?;
72
+
73
+ // Reference matmul
74
+ let ref_out = x.matmul(&w.t()?)?;
75
+
76
+ // NVFP4 matmul via QMatMul
77
+ use candle::quantized::QMatMul;
78
+ let qmatmul = QMatMul::from_arc(std::sync::Arc::new(w_q))?;
79
+ let nvfp4_out = qmatmul.forward(&x)?;
80
+
81
+ let matmul_diff = ref_out.broadcast_sub(&nvfp4_out)?;
82
+ let matmul_max_err = matmul_diff.max_all()?.to_scalar::<f32>()?;
83
+ let matmul_mean_err = matmul_diff.mean_all()?.to_scalar::<f32>()?;
84
+ let matmul_ref_mean = ref_out.abs()?.mean_all()?.to_scalar::<f32>()?;
85
+ println!("MatMul max error: {:.6}", matmul_max_err);
86
+ println!("MatMul mean error: {:.6}", matmul_mean_err);
87
+ println!("MatMul relative error: {:.6}", matmul_mean_err / matmul_ref_mean);
88
+
89
+ println!("\n=== NVFP4 Memory Analysis ===");
90
+ let n = 4096usize;
91
+ let k = 4096usize;
92
+ let fp32_bytes = n * k * 4;
93
+ let nvfp4_bytes = n * (k / 16) * 9; // 9 bytes per 16 elements
94
+ println!("FP32 weight: {:.1} MB", fp32_bytes as f64 / 1024.0 / 1024.0);
95
+ println!("NVFP4 weight: {:.1} MB", nvfp4_bytes as f64 / 1024.0 / 1024.0);
96
+ println!("Compression: {:.2}x", fp32_bytes as f64 / nvfp4_bytes as f64);
97
+
98
+ println!("\n=== Done ===");
99
+ Ok(())
100
+ }