Skip to main content

Work

Struct Work 

Source
pub struct Work {
Show 15 fields pub matmul_retired: u64, pub noc_txns: u64, pub noc_bytes: u64, pub payload_bytes: u64, pub tensix_inst: u64, pub compute_calls: u64, pub engine_operand_tiles: u64, pub sites_used: u64, pub site_noc_bytes: u64, pub engine_noc_bytes: u64, pub site_noc_txns: u64, pub site_matmul_retired: u64, pub dram_bytes: u64, pub dram_tiles: u64, pub onchip_bytes: u64,
}
Expand description

What a program costs the machine, in the units the machine can actually report.

Two views, because they are two different questions and a compiler that owns a Pareto frontier has to keep them apart:

  • the DEVICE TOTALS are what the whole machine spends — the energy question, and the only view the work meter measures, so the only one that can be validated here;
  • the BUSIEST SITE is what one site spends — the balance question, and what a latency model on silicon would be built from. It is PREDICTED STRUCTURE and is deliberately not called a time: ttsim has no clock that measures the program, so nothing here may be quoted as speed.

Minimizing the totals alone would collapse a small problem onto ONE site — that genuinely does move the fewest bytes — which is why the balance term exists and why the objective is stated rather than assumed.

Fields§

§matmul_retired: u64

MVMULs that retire. Closed-form and exact; the conservation law.

§noc_txns: u64

NOC transactions initiated. One per tile on an interleaved buffer, one per multicast.

§noc_bytes: u64

Bytes moved over the NOC, DRAM traffic, multicast delivery and four-byte handshakes alike. This is what the work meter counts, so this is the one that gets validated against the machine.

§payload_bytes: u64

The DATA subset of noc_bytes: tiles, with the four-byte control writes left out.

★ THE OBJECTIVE RANKS ON THIS, NOT ON noc_bytes, and the reason is a pathology it caused. A semaphore atomic moves four bytes and costs a transaction SLOT; putting those four bytes into a bandwidth term let a plan win on bandwidth by eight bytes while losing on transactions by 2,160. Bandwidth and request-rate are different resources and the model keeps them apart.

§tensix_inst: u64

Tensix instructions issued across the device.

§compute_calls: u64

Matrix-engine API invocations the choreography issues across the device.

★ THE ISSUE-COST TERM, AND IT IS A COUNT RATHER THAN A FIT. Two plans can move exactly the same bytes in exactly the same transactions and still differ enormously in what the compute engine is asked to do, because the SUB-BLOCK decides how much arithmetic one call covers: at 4096x4096x256 a 1x8 sub-block issues 16,384 matmul_block calls and a 1x1 sub-block issues 131,072 for identical movement — measured 1,781,904 Tensix instructions against 6,383,760, a 3.58x difference the movement axes cannot see at all.

Predicting the instruction count itself would need per-call constants fitted to something; the CALL COUNT needs nothing — it is read off the same choreography as everything else, and at equal movement and equal retired arithmetic, fewer calls is unambiguously less work.

§engine_operand_tiles: u64

Operand tiles the matrix engines load across the device, each engine by its own rule (SpatialTarget::operand_loads). At equal calls the sub-block’s SHAPE decides it: the fabric’s array is fed a square sub-block’s operands in fewer elements than a long one of the same area, and Tensix’s unpacker, which holds one operand and re-loads the other for every held tile, the reverse.

§sites_used: u64

Sites the program actually placed work on.

§site_noc_bytes: u64

Data bytes crossing the BUSIEST site’s own network interface.

§engine_noc_bytes: u64

Data bytes crossing the BUSIEST MOVEMENT ENGINE of any site.

★ A TENSIX SITE HAS TWO MOVEMENT ENGINES AND THEY RUN CONCURRENTLY, so what paces a site is not what it moves but what its busier engine moves. This is the term that tells apart two plans which fetch exactly the same tiles and differ only in which engine carries which stream — issuing both operand reads together leaves the store an engine to itself and serialises the reads; pairing the second operand with the store overlaps a block’s write with the next block’s reads. Without it the two are indistinguishable, and the compiler picked between them by coin. A site with one engine (SiteSpec::movement_engines) carries every stream on it.

§site_noc_txns: u64

NOC transactions the busiest site initiates.

§site_matmul_retired: u64

MVMULs the busiest site retires.

§dram_bytes: u64

The DRAM subset of noc_bytes: operand reads and output writes of the tensors off the chip’s SRAM tier, excluding L1-to-L1 multicast — what leaves the chip. A tensor the program holds in SRAM (super::residency) moves on chip, and is counted in onchip_bytes instead.

★ THIS IS THE SHARED RESOURCE, and on a GEMM it is the one that binds. Wormhole has SIX DRAM channels against sixty-four sites, so a plan whose sites each fetch their own operands puts an order of magnitude more pressure on DRAM than one that fetches each tile once and multicasts it — even though both deliver the same bytes to the same sites. A model that looked only at per-site traffic would call those two plans equal, and they are not.

§dram_tiles: u64

The tiles behind dram_bytes, whatever each tensor’s width: what a lane that carries one element per cycle is paced by, where a bus is paced by the bytes.

§onchip_bytes: u64

Tile bytes of the tensors the program holds in its SRAM tier — intermediates and carried state it keeps on chip, read and written across the crossbar without leaving it.

Implementations§

Source§

impl Work

Source

pub fn comparable_with(&self, other: &Work) -> bool

The per-axis ratio of self against other, for reporting an efficiency comparison. Only meaningful where matmul_retired agrees — otherwise the two did not compute the same thing.

Trait Implementations§

Source§

impl Clone for Work

Source§

fn clone(&self) -> Work

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for Work

Source§

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

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

impl Default for Work

Source§

fn default() -> Work

Returns the “default value” for a type. Read more
Source§

impl PartialEq for Work

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Work

Source§

impl Eq for Work

Source§

impl StructuralPartialEq for Work

Auto Trait Implementations§

§

impl Freeze for Work

§

impl RefUnwindSafe for Work

§

impl Send for Work

§

impl Sync for Work

§

impl Unpin for Work

§

impl UnsafeUnpin for Work

§

impl UnwindSafe for Work

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
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
§

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

§

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

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

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

§

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, 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> Same for T

Source§

type Output = T

Should always be Self
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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,