Fourier Optics for Training — Presentation 03

Optical Engines in a Training Cluster

Where an optical transform engine would sit in a data-, tensor- and pipeline-parallel training cluster, what a mask rewritten every optimizer step costs against the digital step time, why layer-major scheduling fights pipelines and activation memory, the static Amdahl bound at cluster scale, why the optimizer's frequency transforms (DeMo) are worth bytes on the link rather than FLOPs, and what a measured experiment and simulation say about computing a fixed frequency band in transit, within and across data centres.

Parallelism Mask rewrites Layer-major Pipelines Amdahl DeMo Fixed band Cross-DC
Training step → Parallelism → Mask writes → Schedule → Amdahl bound → The link
00

Topics We'll Cover

Concepts used here, and where they are explained. Each links to a glossary entry: this series glossary, or the Fourier Optics for Inference glossary for the physics and the inference concepts it already explains.

01

The Question for a Cluster, and the Short Answer

Deck 01 counted the transform work in a training step; deck 02 looked at how optics trains itself. This deck asks the systems question: if every accelerator in a training cluster had a Fourier-optical transform engine beside it (FOptInf 01 for the physics), what would a training step look like, and would it be shorter?

The ceiling

  • For a Llama-3-8B-shaped Hyena-2 model, the part a once-per-step mask could hold is 0.13–0.18% of a step (2,048 to 32,768 tokens): an Amdahl bound of 1.001–1.002x.
  • With block-circulant weights (speculative at this scale) it is 9.53–10.07%: a bound of 1.105–1.112x.

The floor under it

  • Weights change every optimizer step, so every step rewrites every mask: 0.52–2.10 s of frames on the illustrative device, against digital steps of 2.05 s (Hyena-2) and 0.15 s (block-circulant).
  • The weight gradient's Fourier-domain products would need a new mask per sequence: minutes per step on one device, about a whole digital step even spread over 64 engines (slide 08). They stay digital.

Short answer: at today's mask rates the engine lengthens the step rather than shortening it, and the frequency transform that genuinely helps a training cluster (DeMo's DCT of the momentum) is worth link bytes, not FLOPs. All numbers come from results.md, written by analysis/train_flop_share.py; the step size (1,048,576 tokens), the cluster (64 GPUs at 400 TFLOP/s sustained) and the device (2-megapixel DMD at 1,031 Hz) are illustrative.

02

Anatomy of a Training Step

One optimizer step processes a global batch (here 1,048,576 tokens) and ends with a single weight update. Four phases, of which only the first two contain transforms:

PhaseWhat it doesWhat it costsTransform work?
ForwardEvery layer on every sequence; activations kept (or checkpointed) for the backwardAbout 2 FLOPs per parameter per tokenLong convolutions: FFT, times H, IFFT
BackwardActivation gradients (dX) and weight gradients (dW), layer by layer in reverseAbout twice the forward: the 6N ruleFFT of G; dU = IFFT(G·conj(H)); dH += G·conj(U)
Gradient syncData-parallel replicas sum their gradients: an all-reduce, or a reduce-scatter and all-gather when optimizer state is sharded (ZeRO, Rajbhandari et al., arXiv:1910.02054)Bytes on the network, proportional to the parametersNone, unless the gradients are compressed (slide 11)
OptimizerAdamW's element-wise update of weights and momentsMemory-bound element-wise work (not counted)None for AdamW; small DCTs for DeMo

The FLOP ledger is checked against the 6N rule: for the transformer variant it gives 46.64 GFLOP per token at 2,048 tokens and 70.80 at 32,768, a ratio of 1.0000 to 6N plus the attention term (results.md §1).

What is new against inference

The weights change at the end of every step. An inference engine's Fourier-plane masks hold the same filter spectra for the life of a deployment; a training engine's masks are stale after each update and must be written again before the next step's forward pass.

03

Parallelism, and Where the Engine Sits

Suppose each accelerator has a transform engine beside it that takes the FFTs and weight-masked products of the layers that accelerator owns. What each engine's mask must hold depends on how the model is split:

Replica 1: pipeline of stages, tensor-parallel inside each stage 1layers 1–8 stage 2layers 9–16 stage 3layers 17–24 stage 4layers 25–32 GPU GPU GPU GPU GPU GPU GPU GPU enginesH and conj H enginesH and conj H enginesH and conj H enginesH and conj H Replicas 2 … d hold the same layers, so their engines hold the same masks replica 2 (same masks) replica 3 (same masks) replica d (same masks) gradient all-reduce / reduce-scatter: bytes, no transforms One step, per engine: write Hmasks forwardall seqs writeconj H backwarddH stays digital all-reduce optimizernew weights
ParallelismWhat it splitsEach engine's mask holds
DataThe batch, across replicasThe whole model's spectra, in every replica: mask writes are replicated, not divided
Tensor (Megatron-LM, Shoeybi et al., arXiv:1909.08053)Each layer's matrices across GPUsA slice of each layer; Hyena's per-channel long convolutions split by channel with no extra communication
PipelineLayers into stagesOnly its stage's layers
Sequence / contextThe sequence dimensionA long convolution needs the whole sequence: splitting it turns one FFT into a distributed FFT with an all-to-all

Megatron's own sequence parallelism splits only the norm and dropout regions along the sequence (Korthikanti et al., arXiv:2205.05198), which a long convolution would tolerate; splitting the convolution itself would not suit an engine that transforms whole rows at once.

04

Masks Change Every Step

A 2-megapixel mask holds a small fraction of the model's filter spectra (FOptInf 02, “Fourier-Plane Mask Capacity”), so an engine cycles through frames as it walks the layers. In inference that cycle serves each batch with fixed weights. In training the weights are new every step, and the backward pass needs them again:

VariantSequenceSequences / stepDigital step timeWeight-mask frames (fwd + bwd)Time
Hyena-22,0485122.05 s5380.52 s
Hyena-28,1921282.05 s2,1482.08 s
Hyena-2 + block-circulant weights2,0485120.15 s5540.54 s
Hyena-2 + block-circulant weights8,1921280.15 s2,1642.10 s

Source: results.md, section “4. Holding the masks”. Illustrative: 2-megapixel DMD at 1,031 Hz, one complex value per pixel (optimistic); 64 GPUs at 400 TFLOP/s; layer-major order.

05

Interactive: Step Time Against Mask Time

Per-token step FLOPs and static shares are embedded from results.json for the four sequence lengths the analysis covers; mask values use the same formula as its mask_budget(). At the defaults the explorer reproduces the slide 04 table.

400
Digital step time
—
Optical-removable
—
Mask writes per engine
—
Net step, not overlapped
—
Net step, fully overlapped
—
Data-by-data masks per engine
—
—

The model, stated plainly. Digital step = per-token step FLOPs × tokens ÷ (GPUs × TFLOP/s), with GPU time proportional to FLOPs (FFTs at the matmul rate). Removable = static share × step: the engine does the static work in zero time. Each engine holds the masks of 1/k of the model (k = tensor × pipeline degree) and writes them twice per pass (forward and backward): 2 × ⌈values ÷ (k × pixels)⌉ frames. Layer-major makes one pass per step; sequence-major makes one per microbatch of m sequences on each of the GPUs ÷ k replicas. Not overlapped (conservative): step − removable + mask time. Fully overlapped: the larger of (step − removable) and mask time. Per-token FLOPs and shares are those at 1,048,576 tokens, held fixed for other step sizes (an approximation: the once-per-step filter transforms shift them slightly at long sequences). The data-by-data figure is what writing the weight gradient's conj(U) masks would cost, spread evenly over all engines.

06

Layer-Major Scheduling Against the Pipeline

Layer-major order passes every sequence of the step through one layer, with that layer's spectra on the mask, before moving on: one write per layer per direction per step. It is the order the slide 04 numbers assume, and the opposite of how large models are trained.

What the mask wants

  • All sequences through one layer, then the next.
  • Mask writes amortised over the whole step.
  • But every layer's activations for the whole step must wait for the backward: 1,048,576 tokens' worth, far beyond accelerator memory without recomputation or offload.

What pipelines and memory want

  • GPipe (Huang et al., arXiv:1811.06965) splits the batch into m microbatches that flow through p stages; the idle “bubble” shrinks as m grows.
  • 1F1B, as used in Megatron-LM (Narayanan et al., arXiv:2104.04473), alternates one forward and one backward microbatch per stage, so a stage holds at most about p microbatches' activations; that paper gives the bubble fraction as (p−1)/m.
ScheduleMask passes per step, per engineActivations held
Layer-major, whole step1 (forward) + 1 (backward)The whole step's
GPipe, m microbatchesm forward + m backwardAll m microbatches per stage (less with recomputation)
1F1B, m microbatchesm forward + m backward, interleaved: the mask flips between H and conj H every microbatchAbout p microbatches per stage

Pipeline parallelism does help in one way: a stage's engine holds only its stage's layers, so each pass has fewer frames (the model-parallel degree in the explorer). It does not help enough: for Hyena-2 at 2,048 tokens even one of 32 stages has more spectra than a 2-megapixel mask holds, so each microbatch still costs frames.

07

Gradient Accumulation as the Compromise

Gradient accumulation already splits an optimizer step into rounds whose gradients are summed before one update. Run each round layer-major over its sequences and the trade is explicit:

a rounds per step → mask writes × a → activations ÷ a
A digital accelerator has no such tension

A GPU reads each layer's weights from HBM as it needs them and can switch layers between kernels. The mask is a weight store that changes only 1,031 times a second on the illustrative device, which is why scheduling, not FLOPs, decides this engine's fate in training.

08

Data-by-Data Products Stay Digital

The filter gradient dH = IFFT(Σ G·conj(U)) multiplies two spectra that both depend on the sequence (the gradient of a convolution is a correlation). With block-circulant weights the weight gradient conj(X)·G depends on every token. Either way, a mask would carry data, and would be new for every sequence or token:

VariantSequenceData-by-data frames per stepTime (one device)Data-by-data part of optical work
Hyena-22,048137,507133 s2.32%
Hyena-28,192137,456133 s2.01%
Hyena-2 + block-circulant weights2,048397,218385 s20.98%
Hyena-2 + block-circulant weights8,192397,168385 s20.49%

Source: results.md, sections 2 and 4 (illustrative device as before).

09

The Static Amdahl Bound for a Step

Static share = FFTs plus the weight-masked products, over all step FLOPs: what an engine with once-per-step masks could take (glossary). If that work became free, the step would be at most 1/(1−share) faster.

VariantSequenceFwd shareStep shareStatic shareAmdahl (static)
Transformer (Llama-3-8B)any0.00%0.00%0.00%1.000x
Hyena-22,0480.20%0.14%0.13%1.001x
Hyena-232,7680.27%0.18%0.18%1.002x
Hybrid 1:3 attention:Hyena2,0480.15%0.10%0.10%1.001x
Hybrid 1:3 attention:Hyena32,7680.18%0.12%0.12%1.001x
Hyena-2 + block-circulant weights2,04813.99%12.06%9.53%1.105x
Hyena-2 + block-circulant weights32,76814.75%12.59%10.07%1.112x

Source: results.md, section “2. A training step”

10

What 1.1x Means at Cluster Scale

A bound of 1.105–1.112x is not nothing at cluster scale: it is roughly a tenth of a training run's GPU-hours, which for a large run is a large bill. That is the case for writing it down. The case against is everything the bound leaves out:

What the 1.1x needs

  • A model with block-circulant weights throughout, unproven at LLM scale (FOptInf 02, “Structured Weights”). For Hyena-2 the bound is 1.001–1.002x.
  • Mask writes fully hidden: at the illustrative rate they are 0.54–2.10 s against a 0.15 s digital step.
  • No time lost to conversions, precision passes or moving data to and from the engine.

What it costs

  • One engine per accelerator, because data parallelism replicates the masks: the engine count grows with the cluster while each removes the same fixed share.
  • Static power for the whole run: lasers, thermal tuning and mask drivers draw power whether or not work arrives. In the inference simulator the break-even static power was a few watts against GPUs that run FFTs well and tens of watts against GPUs that do not (FOptInf 03, “Static Power and Energy per Token”).
  • Area, cost and failure modes added beside every GPU (FOptInf 03, “Area, Cost and Performance per Dollar”).
The comparison that matters

At most a tenth of the GPU time, for the most transform-heavy and least established model, against an extra optical subsystem on every accelerator. The same tenth could be bought by adding about a tenth more GPUs, with no new model architecture, no mask schedule and no analogue precision budget.

11

The Optimizer Step and DeMo

AdamW's update is element-wise and memory-bound: no transforms. One recent optimizer does use them. DeMo (Peng, Quesnelle, Kingma, “DeMo: Decoupled Momentum Optimization”, arXiv:2411.19870, 2024) lets each worker keep its own momentum, takes a DCT of it in small chunks, sends only the largest coefficients (top-k) to the other workers, and removes what it sent from its local momentum. The slow components stay local, decoupled from the exchange.

ParametersDeMo transform FLOPs per stepStep FLOPs (transformer, 4,096)Share
8,029,995,0082.409e+115.059e+164.76e-06

Source: results.md, section “3. The optimizer step and DeMo”: a DCT and an inverse DCT per chunk of 64, at the real-FFT cost.

DeMo as measured. The Compute in Transit experiment (CiT 04) ran it on a 15.8M-parameter GPT (8 layers, width 384, context 256) on TinyStories, with 8 simulated workers of 8 sequences each per step for 3,000 steps. Its mechanics, step by step:

Payload is not wire bytes. A ring all-reduce of B bytes sends 2(N−1)/N·B per worker, whatever N is; DeMo's workers pick different coefficients, so they all-gather instead, and a ring all-gather of P bytes per worker sends (N−1)·P, which grows with N. On 8 workers, per worker per step (BF16 values):

ConfigurationCollectivePayload (bytes)vs denseWire (bytes)vs dense
A  AdamWall-reduce31,666,9441.0x55,417,1521.0x
B  DeMo, top-kall-gather3,957,9608.0x27,705,7202.0x
C  DeMo, fixed band (slide 12)all-gather1,979,18416.0x13,854,2884.0x

Source: the experiment's results.md, section 1 (results site, “What each worker sends”). Top-k's payload counts each index at the bytes a position within a chunk needs; the reference code sends int64 indices, 9,895,920 bytes per step, 2.5x the compact count.

12

Frequency Transforms in Transit: a Fixed Band

Gradient compression is an established line of work: sparsification (Deep Gradient Compression, Lin et al., arXiv:1712.01887), low-rank updates (PowerSGD, Vogels et al., arXiv:1905.13727) and DeMo's DCT. All of them compress at the worker. Could the transform run in the link's data path instead, on bytes that have to move anyway?

Why a fixed band. A photonic link module (Kundu et al., arXiv:2608.21536) can run the transform but not the comparisons top-k needs to find the largest coefficients. A fixed band, the same 1/16 of positions in every chunk every step, needs no comparisons, sends no indices (16x smaller payload, against top-k's 8x), and puts every worker's values at the same positions. The Compute in Transit experiment measured what that substitution costs, on the same 15.8M-parameter model:

ConfigurationSeedsFinal validation lossSteps to 3.158
A  AdamW31.646 ± 0.005400
B  DeMo, top-k, 2-D 64×6431.785 ± 0.007400
C  fixed low band, 1-D 256-point33.124 ± 0.0082,667
C  fixed low band, 1-D 64-point13.1372,800
C  fixed low band, 2-D 64×6433.158 ± 0.009not every seed
D  calibrated band, 2-D 64×6433.087 ± 0.0272,533
F  fixed zig-zag band, 2-D 64×6413.0282,200
F  fixed high band, 2-D 64×6413.244not reached
F  fixed random band, 2-D 64×6412.7001,200

Source: the experiment's results.md, section 1 and “Steps to reach a loss” (loss curves, steps ladder). Steps are the first evaluation (every 200 steps) at or below the target, the mean over seeds; 3.158 is the 2-D low band's own final loss.

Why it loses: captured energy. The share of a tensor's energy (its squared DCT coefficients) a selector keeps at the same k. On worker 0's momentum, averaged after step 200:

ChunksTop-kLow bandZig-zagHigh bandRandom
2-D 64×640.6430.0130.0220.0630.065
1-D 256-point0.4290.1460.1460.0450.049

Source: the experiment's results.md, section 2, runs C, tensor “momentum”, group “all” (results site, “Why a fixed band loses”). A random set keeps about the keep fraction, 1/16.

13

Frequency Transforms in Transit: Where the Band Is Computed

A DCT is linear, so the sum of the workers' bands is the band of the summed delta: unlike top-k, a fixed band can be summed rather than gathered. That gives three places to compute it, beside the measured C (band on the GPU, all-gathered):

delta → fixed band (DCT, keep 1/16) → sum or gather → sign update
VariantWhere the band is computedWire / step, 8 workers in one DC (bytes)Status
C′On the GPU, then a ring all-reduce of the band (linear summing in the transform domain)3,463,572Hypothetical: not run
EIn each worker's pluggable link module, then all-gathered13,854,288Emulated optics, one seed per setting
E′At each data centre's switch, summed there (in-network aggregation); the dense delta goes up to the switch, only the band sum crosses the WAN31,666,944Hypothetical: not run

Source: the simulation's results.md, section 1. C′ and E′ reuse C's and E's measured steps, because summing the band gives the same update as gathering it.

The emulated optics (E). The first design, with the input full scale fixed after calibration and error feedback that removed the exact band, diverged in all six runs (final losses 11.153 to 558.834): the optics' errors were never corrected and the sign update turned a repeated bias into full steps the wrong way. The fix was to feed back the band actually sent, which each sender sees in the all-gather. Repaired, 8 planes: ENOB 6 ends at 3.423, ENOB 8 at 3.017, ENOB 10 at 2.878; perfect optics at 3.141. The best is still 1.09 above top-k (results site, “ENOB and bit planes”). That the repaired optics needs fewer steps than the exact band (1,800 to 3.158 at ENOB 8, against 2,667) is a hypothesis from single seeds.

When it pays: break-even WAN bandwidth (2 data centres of 4 workers; time to 3.158; transform not charged to the module):

ComparisonFaster below
E (pluggable, all-gather) against AdamW or top-kNever, over 0.1–1,000 GB/s
E′ (switch) against AdamW, E's steps1.57 GB/s (12.5 Gb/s)
E′ against AdamW, the exact band's steps0.83 GB/s (6.64 Gb/s)
E′ against top-k, E's steps0.461 GB/s (3.69 Gb/s)
C′ (GPU all-reduce of the band) against AdamW6.58 GB/s (52.7 Gb/s)
C′ against top-k0.799 GB/s (6.39 Gb/s)
E′ against C′, both on the exact band's stepsNever in range

Source: the simulation's results.md, sections 7a and 11 (results site, break-even; CiT 05).

Still speculative

C′ and E′ were never run; the module's coefficients are illustrative except its 9.7 W static power (Kundu et al.); the optics noise model is the series' own; everything rests on one 15.8M-parameter model and 8 workers. The photonics here is a link module computing a band on bytes in flight, not a Fourier engine computing beside the GPU, and the mapping is the Compute in Transit series' own, not any company's.

14

Training Across Data Centres: Time and Energy to a Loss

Saved bytes matter most where the link is slowest: data-parallel workers split across data centres, syncing over a WAN. The training-transit simulation takes the experiment's bytes and measured steps to a loss and asks how long, and how much energy, each way of syncing needs to reach 3.158. Background on where training's bytes go: CiT 02.

Topologies

  • 1 DC × 8 workers, InfiniBand NDR 400G (50 GB/s) per worker
  • 2 DC × 4, or 8 DC × 1, joined by a WAN
  • WAN presets: 100 GbE, 25 GbE, 400G, 800G and an 8 Gb/s share (the last three illustrative)

The model

  • tstep = tcompute + Σrounds (L + bytes / bandwidth)
  • Time to a loss = measured steps × tstep; energy = steps × energy per step
  • An H100 per worker at an MFU of 0.40 (illustrative), 2,048 tokens per worker per step
Variant (2 DC × 4, 100 GbE)Step (ms)Steps to 3.158Time (s)Energy (kJ)Module shareStep, WAN load 0.9 (ms)
A  AdamW, all-reduce4.0754001.631.950.0%26.291
B  DeMo top-k, all-gather2.3154000.931.380.0%12.929
C  band on the GPU, all-gather1.4432,6673.857.270.0%6.552
C′ band on the GPU, all-reduce (hyp.)0.8102,6672.165.900.0%2.975
E  pluggable, all-gather [high]4.8801,8008.7810.687.8%–
E′ summed at the switch (hyp.) [free]3.7261,8006.718.877.2%5.442

Source: the simulation's results.md, sections 2, 5 and 9 (results site, explorer; shared WAN). [high]: module budget 99 GFLOP/s, transform charged; [free]: transform not charged. E's steps are the single-seed ENOB 8 run; the queueing column is the discrete-event engine's mean over 200 syncs, not run for E.

Extrapolations, not measurements

The experiment ran one model size and synced every step. Holding its steps to 3.158 fixed, the simulation gives (2 DC × 4, 100 GbE, seconds to 3.158):

VariantSync every stepEvery 10 (DiLoCo-style)Every 100 (DiLoCo-style)Llama-3-8B shape, every step
A  AdamW1.630.340.21806.45
B  DeMo top-k0.930.270.20453.35
C′ band, GPU all-reduce (hyp.)2.161.401.32961.04
E′ switch (hyp.) [free]6.711.470.943,345.04

Source: the simulation's results.md, section 10 (results site, extrapolations). Syncing every H steps assumes the steps to a loss are unchanged, which DiLoCo (Douillard et al., arXiv:2311.08455) does not promise, since it changes the optimizer too. The model-size row scales bytes and compute with the parameter count. Summary: “What the simulation says”.

Rarer syncs shrink the communication the band saves, and with it the band's only advantage: E′ is behind AdamW at every H. At the Llama-3-8B shape the order is unchanged: top-k first, the in-transit variants last, bound by the module.

15

What Does Not Map at Cluster Scale

WorkWhy a Fourier transform engine does not help
Dense matmuls and attention, forward and backwardNot transforms; the bulk of every step (slide 09)
Weight gradients in the Fourier domainData-by-data: a new mask per sequence or token (slide 08)
Gradient all-reduce, reduce-scatter, all-gatherBytes, not FLOPs; photonic links move them but compute nothing
AdamW and other element-wise optimizersElement-wise and memory-bound
DeMo's DCTs4.76e-06 of the step in 64-point transforms: too small (slide 11)
A fixed band in place of top-k, so a link module can compute itLoses convergence: 3.124–3.158 final loss against 1.785 for top-k on the 15.8M-parameter model; at 2-D 64×64 it keeps 0.013 of the momentum's energy to top-k's 0.643 (slide 12)
The band in a pluggable link moduleNever breaks even with AdamW or top-k over 0.1–1,000 GB/s of WAN; its compute budget is the bottleneck (slide 13)
The band summed at the switchPays only below a few GB/s of WAN (1.57 GB/s against AdamW, 0.461 against top-k, on single-seed steps), and a GPU all-reduce of the band (C′) does better with no module (slide 13)
Microbatched pipelines (GPipe, 1F1B)A mask pass per microbatch; the mask flips between forward and backward spectra (slide 06)
Activation recomputationRepeats the forward transforms and, usually, the mask pass
Long convolutions split by sequence parallelismA distributed FFT with an all-to-all, not one optical pass
Gradient precisionFP8 E5M2 gradients need about 5.3–5.8 ENOB and BF16 about 10.3–10.7 (results.md §5; deck 02)

And the costs that apply even where it maps: a mask rewritten every step, conversions per value, static power on every accelerator for the whole run, and one engine per data-parallel replica because the masks are replicated.

16

What to Take Away

For this deck and for the series: