Skip to main content

ZShape

Struct ZShape 

Source
pub struct ZShape {
    pub h_lat: usize,
    pub w_lat: usize,
    pub grid: (usize, usize),
    pub n_img: usize,
    pub n_img_p: usize,
    pub l: usize,
    pub l_p: usize,
}
Expand description

Token geometry of one (resolution, prompt length).

Fields§

§h_lat: usize

Latent size (H/8, W/8).

§w_lat: usize§grid: (usize, usize)

Patch grid (H/16, W/16).

§n_img: usize

n_img = grid.0 · grid.1, n_img_p = ceil32(n_img).

§n_img_p: usize§l: usize

Caption tokens L and ceil32(L).

§l_p: usize

Implementations§

Source§

impl ZShape

Source

pub fn new(height: usize, width: usize, l: usize) -> Self

From the image size in pixels (multiples of 16) and the caption length.

Examples found in repository?
examples/zimage_devcheck.rs (line 56)
44fn main() {
45    unsafe { std::env::set_var("CMF_GPU", "1") };
46    let a: Vec<String> = std::env::args().collect();
47    let model = Arc::new(cortiq_core::CmfModel::open(&a[1]).unwrap());
48    let dit = ZImageDit::from_cmf(&model).unwrap();
49    let od = std::path::Path::new(&a[2]);
50    let case = &a[3];
51    let (o, meta) = read_st(&od.join(format!("dit_{case}_fp32.safetensors")));
52    let (hh, ww, l) = (meta_usize(&meta, "H"), meta_usize(&meta, "W"), meta_usize(&meta, "L"));
53    let t = o["t_model"][0];
54    let cap = &o["cap"];
55    let x_in = &o["x_in"];
56    let shape = ZShape::new(hh, ww, l);
57    let mods = dit.mods_for_steps(&[t]);
58    let fs = dit.final_scale_for_steps(&[t]);
59    let rope = zimage::ids_and_rope(shape.grid, l, dit.cfg.rope_theta, dit.cfg.axes_dims);
60    // caption: device-refined (prepare) vs CPU-refined
61    let prep = dit.prepare(cap, shape, 1, None).unwrap();
62    println!("device prepared: {}", prep.device);
63    let mut cap_cpu = dit.embed_caption(cap, l);
64    dit.refine_caption_cpu(&mut cap_cpu, (&rope.cap.0, &rope.cap.1));
65    println!("cr1_out  dev vs cpu {:.3e}   cpu vs oracle {:.3e}   dev vs oracle {:.3e}",
66        rel(&prep.cap, &cap_cpu), rel(&cap_cpu, &o["cr1_out"]), rel(&prep.cap, &o["cr1_out"]));
67    let (c, lh, lw) = (dit.cfg.in_channels, hh / 8, ww / 8);
68    let x_tok = zimage::pad_rows_repeat_last(&zimage::patchify(x_in, c, lh, lw), shape.n_img, shape.n_img_p, dit.geom().patch_dim);
69    let tapdir = std::env::var("CMF_ZI_TAPS").unwrap_or("/root/zb/taps".into());
70    let v_dev = dit.step(&prep, 0, &x_tok, &mods, &fs);
71    // Replays must be stateless: the same inputs again, and a different
72    // step's mods in between.
73    let mods2 = dit.mods_for_steps(&[t * 0.5 + 0.25]);
74    let fs2 = dit.final_scale_for_steps(&[t * 0.5 + 0.25]);
75    let _ = dit.step(&prep, 1, &x_tok, &mods2, &fs2);
76    let v_dev2 = dit.step(&prep, 2, &x_tok, &mods, &fs);
77    println!("replay   dev2 vs dev1 {:.3e}", rel(&v_dev2, &v_dev));
78    let mut taps: Vec<(String, Vec<f32>)> = Vec::new();
79    // the CPU path must see the SAME (device-refined) caption to isolate the DiT
80    let mut prep_cpu = prep;
81    prep_cpu.device = false;
82    let v_cpu = dit.step_cpu_taps(&prep_cpu, &x_tok, &mods, &fs, &mut |n, v| taps.push((n.to_string(), v.to_vec())));
83    println!("v        dev vs cpu {:.3e}   cpu vs oracle(final_out) {:.3e}", rel(&v_dev, &v_cpu), rel(&v_cpu, &o["final_out"]));
84    for (n, v) in &taps {
85        let p = std::path::Path::new(&tapdir).join("step0").join(format!("{n}.f32"));
86        if let Ok(b) = std::fs::read(&p) {
87            let d: Vec<f32> = b.chunks_exact(4).map(|c| f32::from_le_bytes(c.try_into().unwrap())).collect();
88            let or = o.get(n.as_str()).map(|w| format!("{:.3e}", rel(v, w))).unwrap_or_default();
89            println!("{n:10} dev vs cpu {:.3e}   (cpu vs oracle {or})", rel(&d, v));
90        }
91    }
92}
More examples
Hide additional examples
examples/zimage_metal_check.rs (line 71)
58fn main() {
59    let a: Vec<String> = std::env::args().collect();
60    let model = Arc::new(cortiq_core::CmfModel::open(&a[1]).unwrap());
61    let dit = ZImageDit::from_cmf(&model).unwrap();
62    let od = std::path::Path::new(&a[2]);
63    let case = &a[3];
64    let reps: usize = a.get(4).and_then(|v| v.parse().ok()).unwrap_or(2);
65    let (o, meta) = read_st(&od.join(format!("dit_{case}_fp32.safetensors")));
66    let bf = od.join(format!("dit_{case}_bf16.safetensors"));
67    let (hh, ww, l) = (meta_usize(&meta, "H"), meta_usize(&meta, "W"), meta_usize(&meta, "L"));
68    let t = o["t_model"][0];
69    let cap = &o["cap"];
70    let x_in = &o["x_in"];
71    let shape = ZShape::new(hh, ww, l);
72    let mods = dit.mods_for_steps(&[t]);
73    let fs = dit.final_scale_for_steps(&[t]);
74    let rope = zimage::ids_and_rope(shape.grid, l, dit.cfg.rope_theta, dit.cfg.axes_dims);
75    let t0 = std::time::Instant::now();
76    let prep = dit.prepare(cap, shape, 1, None).unwrap();
77    println!("device prepared: {} ({:.3}s incl. caption refine)", prep.device, t0.elapsed().as_secs_f64());
78    let mut cap_cpu = dit.embed_caption(cap, l);
79    dit.refine_caption_cpu(&mut cap_cpu, (&rope.cap.0, &rope.cap.1));
80    if let Some(cr) = o.get("cr1_out") {
81        println!(
82            "caption  dev vs cpu {:.3e}   cpu vs oracle {:.3e}   dev vs oracle {:.3e}",
83            rel(&prep.cap, &cap_cpu),
84            rel(&cap_cpu, cr),
85            rel(&prep.cap, cr)
86        );
87    }
88    let (c, lh, lw) = (dit.cfg.in_channels, hh / 8, ww / 8);
89    let x_tok = zimage::pad_rows_repeat_last(&zimage::patchify(x_in, c, lh, lw), shape.n_img, shape.n_img_p, dit.geom().patch_dim);
90    let mut v_dev = Vec::new();
91    for r in 0..reps {
92        let ts = std::time::Instant::now();
93        let v = dit.step(&prep, 0, &x_tok, &mods, &fs);
94        println!("device step {r}: {:.3}s", ts.elapsed().as_secs_f64());
95        if r > 0 {
96            println!("replay   {:.3e}", rel(&v, &v_dev));
97        }
98        v_dev = v;
99    }
100    let orc = &o["final_out"];
101    println!("v        dev vs oracle fp32 {:.3e}", rel(&v_dev, orc));
102    if bf.exists() {
103        let (ob, _) = read_st(&bf);
104        if let Some(vb) = ob.get("final_out") {
105            println!("v        oracle bf16 vs fp32 {:.3e} (the diffusers-bf16 floor)", rel(vb, orc));
106        }
107    }
108    if std::env::var("ZC_NOCPU").as_deref() != Ok("1") {
109        let mut prep_cpu = dit.prepare_with(cap, shape, 2, None, false).unwrap();
110        prep_cpu.cap = prep.cap.clone();
111        let ts = std::time::Instant::now();
112        let v_cpu = dit.step_cpu(&prep_cpu, &x_tok, &mods, &fs);
113        println!("cpu step: {:.3}s", ts.elapsed().as_secs_f64());
114        println!(
115            "v        dev vs cpu {:.3e}   cpu vs oracle fp32 {:.3e}",
116            rel(&v_dev, &v_cpu),
117            rel(&v_cpu, orc)
118        );
119    }
120    if std::env::var("ZC_NEG").as_deref() == Ok("1") {
121        // batch-2 pair: item 1 = the same caption at a different padded
122        // length is not available here, so use the same caption; the pair
123        // must reproduce the single forward exactly per item
124        let mut p2 = dit.prepare(cap, shape, 7, None).unwrap();
125        p2.device = false;
126        let pair_key = 9;
127        let okp = dit.attach_device_pair(&prep, &p2, pair_key, None);
128        println!("pair prepared: {okp}");
129        if okp {
130            let ts = std::time::Instant::now();
131            let r = dit.step_pair_device(pair_key, shape.n_img, 0, &x_tok, &mods, &fs).unwrap();
132            println!("pair step: {:.3}s", ts.elapsed().as_secs_f64());
133            println!("pair     item0 vs single {:.3e}   item1 vs single {:.3e}", rel(&r.0, &v_dev), rel(&r.1, &v_dev));
134        }
135    }
136}
examples/zimage_stepcheck.rs (line 48)
32fn main() {
33    let a: Vec<String> = std::env::args().collect();
34    let model = Arc::new(cortiq_core::CmfModel::open(&a[1]).unwrap());
35    let (prompt, hh, ww) = (&a[2], a[3].parse::<usize>().unwrap(), a[4].parse::<usize>().unwrap());
36    let (steps, shift, i) = (a[5].parse::<usize>().unwrap(), a[6].parse::<f32>().unwrap(), a[7].parse::<usize>().unwrap());
37    let tok = Tokenizer::from_bytes(model.vocab.as_deref().unwrap()).unwrap();
38    let ids = cortiq_engine::zimagegen::prompt_ids(&tok, prompt, 512);
39    let cap = {
40        let _p = cortiq_engine::gpu::pause_gpu();
41        cortiq_engine::qwen3te::Qwen3Encoder::from_cmf(&model).unwrap().encode(&ids)
42    };
43    let dit = ZImageDit::from_cmf(&model).unwrap();
44    let sig = zimage::sigmas_torch_f32(steps, shift);
45    let t = zimage::t_model(sig[i]);
46    let mods = dit.mods_for_steps(&[t]);
47    let fs = dit.final_scale_for_steps(&[t]);
48    let shape = ZShape::new(hh, ww, ids.len());
49    let prep = dit.prepare(&cap, shape, 1, None).unwrap();
50    println!("device prepared: {}", prep.device);
51    let (c, lh, lw) = (dit.cfg.in_channels, hh / 8, ww / 8);
52    let lat = |dir: &str| -> Vec<f32> {
53        if i == 0 {
54            read_f32(&std::env::var("CMF_INIT_LATENT").unwrap())
55        } else {
56            read_f32(&format!("{dir}/lat_{i}.f32"))
57        }
58    };
59    let xa = lat(&a[8]);
60    // `ZC_NEG=<negative prompt>`: the CFG pair as one batch-2 device
61    // forward against the two items stepped one by one.
62    if let Ok(neg) = std::env::var("ZC_NEG") {
63        let nids = cortiq_engine::zimagegen::prompt_ids(&tok, &neg, 512);
64        let ncap = {
65            let _p = cortiq_engine::gpu::pause_gpu();
66            cortiq_engine::qwen3te::Qwen3Encoder::from_cmf(&model).unwrap().encode(&nids)
67        };
68        let mut np = dit.prepare(&ncap, ZShape::new(hh, ww, nids.len()), 2, None).unwrap();
69        let tok_a = dit.tokens(&xa, &shape);
70        // `ZC_TAPS=<dir>`: every block's residual stream of the three
71        // forwards (single pos, single neg, pair) into <dir>/{pos,neg,pair},
72        // then compared block by block (the pair's item rows vs the single).
73        let taps = std::env::var("ZC_TAPS").ok();
74        let set_taps = |sub: &str| {
75            if let Some(d) = &taps {
76                unsafe { std::env::set_var("CMF_ZI_TAPS", format!("{d}/{sub}")) };
77            }
78        };
79        set_taps("pos");
80        let vp = dit.step(&prep, i, &tok_a, &mods, &fs);
81        set_taps("neg");
82        let vn = dit.step(&np, i, &tok_a, &mods, &fs);
83        unsafe { std::env::remove_var("CMF_ZI_TAPS") };
84        np.device = false;
85        let vn_cpu = dit.step(&np, i, &tok_a, &mods, &fs);
86        np.device = true;
87        // `ZC_SWAP=1`: the pair as (neg, pos) — tells a positional cause
88        // (item 0 vs item 1) from a content one (the caption length).
89        let swap = std::env::var("ZC_SWAP").as_deref() == Ok("1");
90        let (first, second) = if swap { (&np, &prep) } else { (&prep, &np) };
91        let ok = dit.attach_device_pair(first, second, 3, None);
92        println!(
93            "pair prepared: {ok}  (pos L = {}, neg L = {}, n_img_p {}, order {})",
94            ids.len(),
95            nids.len(),
96            shape.n_img_p,
97            if swap { "neg,pos" } else { "pos,neg" }
98        );
99        set_taps("pair");
100        if let Some((p0, p1)) = dit.step_pair_device(3, shape.n_img, i, &tok_a, &mods, &fs) {
101            let (pp, pn) = if swap { (p1, p0) } else { (p0, p1) };
102            let nan = pp.iter().chain(&pn).filter(|v| !v.is_finite()).count();
103            println!("pair vs singles: pos {:.3e}  neg {:.3e}  non-finite {nan}   single neg dev vs cpu {:.3e}",
104                rel(&pp, &vp), rel(&pn, &vn), rel(&vn, &vn_cpu));
105        }
106        unsafe { std::env::remove_var("CMF_ZI_TAPS") };
107        if let Some(d) = &taps {
108            // Row layout of the pair: image stage [item][n_img_p]; joint
109            // stage [item0: n_img_p + cp0][item1: n_img_p + cp1].
110            let h = dit.cfg.dim;
111            let cp = |l: usize| l.div_ceil(32) * 32;
112            let (cp_pos, cp_neg) = (cp(ids.len()), cp(nids.len()));
113            let (cp0, cp1) = if swap { (cp_neg, cp_pos) } else { (cp_pos, cp_neg) };
114            let nip = shape.n_img_p;
115            let rd = |p: String| -> Option<Vec<f32>> {
116                std::fs::read(&p).ok().map(|b| b.chunks_exact(4).map(|c| f32::from_le_bytes(c.try_into().unwrap())).collect())
117            };
118            let mut names: Vec<String> = (0..2).map(|k| format!("nr{k}_out")).collect();
119            names.extend((0..dit.cfg.n_layers).map(|k| format!("l{k}_out")));
120            for n in names {
121                let (Some(sp), Some(sn), Some(pr)) = (
122                    rd(format!("{d}/pos/step{i}/{n}.f32")),
123                    rd(format!("{d}/neg/step{i}/{n}.f32")),
124                    rd(format!("{d}/pair/step{i}/{n}.f32")),
125                ) else {
126                    continue;
127                };
128                let (r0, r1) = if n.starts_with("nr") {
129                    ((0, nip), (nip, nip))
130                } else {
131                    ((0, nip + cp0), (nip + cp0, nip + cp1))
132                };
133                let item = |r: (usize, usize)| &pr[r.0 * h..(r.0 + r.1) * h];
134                let (ip, ineg) = if swap { (item(r1), item(r0)) } else { (item(r0), item(r1)) };
135                // image rows and caption rows separately
136                let split = |v: &[f32]| (v[..nip * h].to_vec(), v[nip * h..].to_vec());
137                let (pi, pc) = split(ip);
138                let (spi, spc) = split(&sp[..ip.len().min(sp.len())]);
139                println!(
140                    "{n:9} pos: img {:.3e} cap {:.3e}   neg: all {:.3e}",
141                    rel(&pi, &spi),
142                    if pc.is_empty() { 0.0 } else { rel(&pc, &spc) },
143                    rel(ineg, &sn[..ineg.len().min(sn.len())])
144                );
145            }
146        }
147        return;
148    }
149    let tok_a = dit.tokens(&xa, &shape);
150    let va_dev = zimage::unpatchify(&dit.step(&prep, i, &tok_a, &mods, &fs), c, lh, lw);
151    let mut hp = zimage::ZPrepared { device: false, ..prep };
152    let va_cpu = zimage::unpatchify(&dit.step(&hp, i, &tok_a, &mods, &fs), c, lh, lw);
153    let va_tr = read_f32(&format!("{}/v_{i}.f32", a[8]));
154    println!("step {i} on A's lat: dev vs cpu {:.3e}   cpu vs A's v {:.3e}   dev vs A's v {:.3e}",
155        rel(&va_dev, &va_cpu), rel(&va_cpu, &va_tr), rel(&va_dev, &va_tr));
156    if let Some(b) = a.get(9) {
157        hp.device = true;
158        let xb = lat(b);
159        let vb_dev = zimage::unpatchify(&dit.step(&hp, i, &dit.tokens(&xb, &shape), &mods, &fs), c, lh, lw);
160        println!("inputs A vs B {:.3e}   device outputs {:.3e}   (B's own v {:.3e})",
161            rel(&xb, &xa), rel(&vb_dev, &va_dev), rel(&read_f32(&format!("{b}/v_{i}.f32")), &va_dev));
162    }
163}
Source

pub fn seq(&self) -> usize

S = n_img_p + l_p.

Trait Implementations§

Source§

impl Clone for ZShape

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for ZShape

Source§

impl Debug for ZShape

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for ZShape

Source§

impl PartialEq for ZShape

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ZShape

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more