EvaluatedApplications.AlgFormer.Gpu
1.16.1
dotnet add package EvaluatedApplications.AlgFormer.Gpu --version 1.16.1
NuGet\Install-Package EvaluatedApplications.AlgFormer.Gpu -Version 1.16.1
<PackageReference Include="EvaluatedApplications.AlgFormer.Gpu" Version="1.16.1" />
<PackageVersion Include="EvaluatedApplications.AlgFormer.Gpu" Version="1.16.1" />
<PackageReference Include="EvaluatedApplications.AlgFormer.Gpu" />
paket add EvaluatedApplications.AlgFormer.Gpu --version 1.16.1
#r "nuget: EvaluatedApplications.AlgFormer.Gpu, 1.16.1"
#:package EvaluatedApplications.AlgFormer.Gpu@1.16.1
#addin nuget:?package=EvaluatedApplications.AlgFormer.Gpu&version=1.16.1
#tool nuget:?package=EvaluatedApplications.AlgFormer.Gpu&version=1.16.1
AlgFormer.Gpu
Optional ILGPU/CUDA acceleration for the EvaluatedApplications.AlgFormer
HoloFormer resonator-attention model (plus a deprecated twin for the older softmax-attention AlgFormer core).
Every GPU kernel is gradchecked against the CPU model as the correctness oracle, fp32 on the GPU vs fp64 on the
CPU, so results are float-close, not bit-identical. This page is the only documentation shipped with the
package (binary-only NuGet, no separate docs site): every public type, method, and option is covered below with a
compiling example.
Every code block below was pasted into a throwaway console project that ProjectReferences this package and
built against the current public surface. Blocks marked "continuing from" reuse the Quick Start variables.
Table of contents
- Quick start
- Gotchas you must know
GpuDevice: device detectionGpuHoloTrainer: the production entry pointGpuHoloModel: the low-level engine- Preference (DPO) training
- Coherence gates, rising memory and atom preference on the GPU
- Pleroma page transforms
GpuOps: standalone kernel verify/bench- Deprecated non-holo twin:
GpuModel/GpuTrainer - Maturity notes
- License
Quick start
dotnet add package EvaluatedApplications.AlgFormer.Gpu
using PrismFormer;
using PrismFormer.Gpu;
// Device auto-detect: a real CUDA GPU if present, otherwise ILGPU's own CPU accelerator backend running the
// SAME kernels, no branching needed in your code either way.
Console.WriteLine(GpuDevice.Describe); // "GPU: <name> (<MB> MB)" or "CPU (no CUDA GPU)"
// A small CPU HoloFormer model, the GPU trainer wraps it and the CPU copy stays the source of truth.
var model = new HoloFormer(vocab: 16, shifts: 4, layers: 2, maxContext: 6, dModel: 8);
using var trainer = new GpuHoloTrainer(model);
// batch is IReadOnlyList<(int[] Ctx, int Target)>
var batch = new (int[] Ctx, int Target)[]
{
(new[] { 1, 2, 3 }, 4),
(new[] { 5, 4, 3 }, 2),
};
double loss = trainer.TrainBatch(batch, lr: 5e-2); // runs forward+backward on the GPU, one CPU Adam step, updates `model` in place
trainer.SyncToGpu(); // GPU is one step behind the just-updated CPU model, push it across
float[] logits = trainer.Logits(new[] { 1, 2, 3 }); // GPU inference
Gotchas you must know
- CUDA detection + CPU fallback is automatic and silent.
GpuDevice.HasGpu == falseon a box with no NVIDIA driver is a valid, expected outcome, not a bug, the exact same kernels run on ILGPU's CPU accelerator, just slower. Don't branch your own code on it; check it only for logging/diagnostics. - The CPU model is always the source of truth. Everything you serve, save, or bleed/absorb reads the CPU
HoloFormer/AlgFormerpassed into the trainer's constructor, never the GPU buffers directly. - Classic (default) path: GPU goes stale after every CPU-side weight change.
TrainBatch/TrainBatchAllPosre-sync CPU→GPU automatically each call, but an out-of-band inference call (Logits/StackIterLogits) after a manual CPU edit needs an explicittrainer.SyncToGpu()first. - Fused-Adam mode (
FusedGpuAdam = true) inverts authority. The GPU holds the LIVE params for the duration of the run; the CPU model lags until you callSyncToCpu(). CallSyncToCpu()before reading/saving/serving the CPU model whenever fused mode is on. Do not callSyncToGpu()mid-run, that clobbers the live GPU params with the stale CPU copy; it's only for pushing an out-of-band CPU change (a bleed/absorb) back IN. SyncToCpu()syncs PARAMS ONLY. In fused mode the Adam m/v moments live on the GPU and are not touched bySyncToCpu. For an exact resume, also checkpointSerializeFusedOptimizer()/RestoreFusedOptimizer(), restore params first, then optimizer state.- Rebuild the trainer after the model's SHAPE changes (layer count, dims, e.g. after a HoloFormer "grow").
A new
GpuHoloTrainer/GpuHoloModelis cheap to construct (only params re-upload); the existing one's device buffers are sized to the old shape and cannot be resized in place. - fp32 on GPU, fp64 CPU oracle. Never expect bit-exact results between the two paths, use a loose tolerance (around 1e-4 to 1e-6) when comparing.
d(the model's channel dimension) must be even, the resonator attention is complex-pair math (GpuHoloModelthrowsInvalidOperationExceptionotherwise).- Thread-safety:
GpuDevice.Acceleratoris ONE process-wide singleton, shared by everyGpuHoloModel/GpuHoloTrainerin the process. ILGPU documents accelerators as not thread-safe, never call GPU methods on this package's types concurrently from two threads. Build/train/infer serially (interleaved on one thread is fine; a background-thread snapshot read is explicitly NOT supported, seeRefreshSnapshotbelow). - Nothing in this package is license-gated or tiered. Every capability documented below, including the experimental ones, is available with no key and no "Pro" tier.
GpuModel/GpuTrainer(the non-holo softmax-attention twin) are[Obsolete]. They still build, run, and gradcheck, but get no further work, useGpuHoloModel/GpuHoloTrainerfor anything new.
GpuDevice: device detection
Static, thread-safe, lazy-cached: probes for a CUDA GPU once per process and caches the result.
| Member | Purpose |
|---|---|
GpuDevice.HasGpu |
true iff a real CUDA GPU was found (not the CPU fallback). |
GpuDevice.Accelerator |
The ILGPU Accelerator in use (CUDA or CPU fallback), or null if ILGPU/the driver is unavailable entirely. |
GpuDevice.Describe |
Human-readable device line for logs: "GPU: <name> (<MB> MB)" or "CPU (no CUDA GPU)". |
GpuDevice.MemoryMb |
Total device memory in MB (0 if no accelerator), useful for sizing a GPU sub-batch to the card. |
GpuDevice.Shutdown() |
Disposes the cached accelerator/context. Call at process exit; a later GPU call re-initializes lazily. |
using PrismFormer.Gpu;
Console.WriteLine(GpuDevice.Describe);
bool hasGpu = GpuDevice.HasGpu;
long memMb = GpuDevice.MemoryMb;
var accelerator = GpuDevice.Accelerator; // null only if ILGPU/driver is missing entirely
// ... use the package ...
GpuDevice.Shutdown(); // at process exit
GpuHoloTrainer: the production entry point
GpuHoloTrainer wraps a CPU HoloFormer, runs batched forward+backward on the GPU, and keeps the CPU model as
the checkpoint/serve source of truth. Construct one per model shape; rebuild it whenever the model's layer count
or dimensions change.
public GpuHoloTrainer(HoloFormer cpu, int tokenBudget = 24576, double clip = 10.0)
tokenBudget seeds the adaptive GPU dispatch-size climb (it self-tunes from there); clip is the global gradient-
norm clip applied on every Adam step (classic and fused paths alike).
Core training
| Member | Purpose |
|---|---|
TrainBatch(batch, lr) |
One training step over IReadOnlyList<(int[] Ctx, int Target)>, prefix+next-token examples. Updates the CPU model in place, returns mean cross-entropy loss. Over-length windows run concurrently on the CPU; routes through the fused path automatically if FusedGpuAdam is on. |
TrainBatchAllPos(seqs, lr) |
ALL-POSITIONS training: each item is a full token sequence (not prefix+target); scores the last ScorePositions transitions in one forward (the causal resonator makes every position a valid next-token prediction), up to ~ScorePositions× the gradient signal per forward at the same forward cost. Sequences up to MaxContext+1 tokens are scored whole; longer ones are truncated to their scored tail. |
TrainBatchCoop(gpuBatch, cpuExtra, lr) |
Cooperative step: the GPU trains the full gpuBatch while the CPU concurrently trains cpuExtra additional windows as pure bonus work (grads sum exactly), a TCP-Reno-style controller (CpuShare) sizes cpuExtra so the CPU stays hidden under the GPU's time. Returns mean loss over the combined effective batch. |
// continuing from the Quick Start model/trainer/batch above
loss = trainer.TrainBatch(batch, lr: 5e-2);
var seqs = new int[][] { new[] { 1, 2, 3, 4, 5 }, new[] { 2, 3, 4, 5, 6 } };
double lossAllPos = trainer.TrainBatchAllPos(seqs, lr: 5e-2);
double lossCoop = trainer.TrainBatchCoop(batch, Array.Empty<(int[] Ctx, int Target)>(), lr: 5e-2);
Inference
| Member | Purpose |
|---|---|
Logits(context) |
Forward-only GPU inference: logits at the last position of context. Call SyncToGpu() first if the CPU weights changed since the last train/sync call. |
StackIterLogits(context, K, alpha) |
Serve at PER-LAYER weight-tied K depth (see StackK below): alpha is per-layer (alpha[l], length must equal the model's layer count). Same sync contract as Logits. |
trainer.SyncToGpu();
logits = trainer.Logits(new[] { 1, 2, 3 });
float[] stackLogits = trainer.StackIterLogits(new[] { 1, 2, 3 }, K: 2, alpha: new float[] { 1f, 1f });
Sync & snapshotting
| Member | Purpose |
|---|---|
SyncToGpu() |
Push the CPU model's current weights onto the GPU. In fused mode this RE-SEEDS the GPU as authoritative, only call it to push an out-of-band CPU change (bleed/absorb, or a per-batch CPU fallback step) back in; never mid-fused-run. |
SyncToCpu() |
Pull the live GPU params back onto the CPU source-of-truth model. PARAMS ONLY, see the Gotchas above for the optimizer-state caveat in fused mode. |
NewSnapshot() |
Build a standalone GpuHoloModel at this trainer's shape, decoupled from the trainer's own buffers, the target for RefreshSnapshot. |
RefreshSnapshot(snapshot) |
Lock-free GPU-to-GPU copy of this trainer's LIVE params into a separate snapshot model, for contention-free inference against an immutable point-in-time copy. Call serially with the trainer's own GPU calls, see the thread-safety gotcha above. |
using var snapshot = trainer.NewSnapshot();
trainer.RefreshSnapshot(snapshot);
float[] snapLogits = snapshot.StackIterForward(new[] { new[] { 1, 2, 3 } }, K: 1, alpha: new float[] { 1f, 1f })[0];
trainer.SyncToCpu(); // before saving/serving the CPU model
Fused on-GPU Adam (opt-in)
Default OFF (FusedGpuAdam = false): the classic path reads the full gradient back to the host and takes a CPU
double-precision Adam step every batch, production-proven, and the CPU model is continuously authoritative.
Setting FusedGpuAdam = true keeps the Adam m/v moments AND the param update resident on the GPU, removing the
per-batch full-gradient readback, also production-proven (it's the mode the live HoloEngine trains with), but it
inverts weight authority to the GPU for the run (see Gotchas).
| Member | Purpose |
|---|---|
FusedGpuAdam (bool, default false) |
Opt in to the on-GPU Adam step; routes TrainBatch/TrainBatchAllPos through the fused path. |
AdamStepsSkipped (long) |
Count of fused Adam steps DROPPED because the batch's global grad-norm wasn't finite (NaN/Inf guard), watch for an endless-skip run. |
CpuAdamStepsSkipped (long) |
The same guard's counter on the classic (CPU-Adam) path. |
SerializeFusedOptimizer() |
Checkpoint the GPU-resident Adam m/v moments + step counter to a byte[] (fp32 bit-exact round-trip). Pair with SyncToCpu() at a checkpoint boundary. |
RestoreFusedOptimizer(blob) |
Restore the Adam state from a blob produced by SerializeFusedOptimizer. Restore params first (rebuild the trainer from saved CPU params), then call this. Throws ArgumentException on a shape mismatch. |
var fusedModel = new HoloFormer(vocab: 16, shifts: 4, layers: 2, maxContext: 6, dModel: 8);
using var fusedTrainer = new GpuHoloTrainer(fusedModel);
fusedTrainer.FusedGpuAdam = true;
fusedTrainer.StackK = 2;
double fusedLoss = fusedTrainer.TrainBatch(batch, lr: 5e-2);
fusedTrainer.SyncToCpu(); // REQUIRED before reading/saving fusedModel
byte[] optState = fusedTrainer.SerializeFusedOptimizer(); // checkpoint the GPU-resident Adam moments
fusedTrainer.RestoreFusedOptimizer(optState); // resume with momentum intact
long skipped = fusedTrainer.AdamStepsSkipped;
ADAM & EVE (opt-in)
A per-layer directional gradient gate that nudges Adam's step toward (or away from) the model's own
decode-codebook usable range, layered on top of the fused Adam step. Live in production: this package ships
it default OFF, but PrismStudio's HoloEngine has trained with it enabled (EveEnabled = true via FusedGpuAdam)
as its active optimizer path since 2026-09-24, it is not an unused experiment. Requires FusedGpuAdam = true
and StackK > 1 (throws NotSupportedException otherwise, since the gate needs the per-layer K path).
Member (on GpuHoloTrainer) |
Purpose |
|---|---|
EveEnabled (bool, default false) |
Master opt-in switch. |
EveK (double, default 1.0) |
Envelope multiplier on the codebook-derived usable range (floor/ceiling × EveK). |
EveEps (double, default 1e-3) |
Top-1 slack target fed to the range derivation. |
EveNudge (double, default 0.05) |
The push-pull magnitude e. PINNED by the design spec, don't sweep without a pre-registration amendment. |
EveDistanceScaled (bool, default false) |
Replace the flat ±e gain with one that scales by how far outside the range the layer sits. |
EveInBoost (double, default 1.0) |
Only meaningful with EveDistanceScaled=true: scales the inward (toward-band) boost independently of the outward damping. |
EveBandCap (bool, default false) |
REPLACES the whole directional gate with a hard, ratcheting ceiling cap (ignores EveNudge/EveDistanceScaled/EveInBoost while on). |
EveInterval (int, default 16) |
Recompute cadence for the gate decision (the Adam step itself is never skipped), 1 reproduces every-step recompute exactly. |
var eveModel = new HoloFormer(vocab: 16, shifts: 4, layers: 2, maxContext: 6, dModel: 8);
using var eveTrainer = new GpuHoloTrainer(eveModel);
eveTrainer.FusedGpuAdam = true;
eveTrainer.StackK = 2; // required: ADAM & EVE gates per-layer output
eveTrainer.EveEnabled = true;
eveTrainer.EveBandCap = true; // or leave false for the softer EveNudge/EveDistanceScaled/EveInBoost gate
double eveLoss = eveTrainer.TrainBatch(batch, lr: 5e-2);
Depth knobs
These select which "depth" strategy TrainBatch/TrainBatchAllPos/Logits/StackIterLogits use underneath.
IterCount and StackK are mutually exclusive, pick one.
| Member | Default | Purpose |
|---|---|---|
IterCount |
1 (off) |
Whole-STACK weight-tied iteration depth. L=1 models only. |
StackK |
1 (off) |
PER-LAYER weight-tied K: each of the L layers applies its own banks K times, α-gated. Works for any layer count, the one to use for L>1 depth. |
ScorePositions |
1 |
How many trailing transitions TrainBatchAllPos scores per sequence (>1 harvests more gradient signal per forward at the same forward cost). |
IterAlpha |
all 1f, sized to layer count |
Per-layer α on the EXTRA iterations' residual, lets a newly-added layer ramp its own α from 0 while already-settled layers stay pinned. A uniform array reproduces the old shared-scalar behavior. |
IterClean |
false |
Full-vocab attractor cleanup between weight-tied iterations. |
IterTau |
32 |
Temperature for IterClean's softmax attractor. |
trainer.StackK = 2;
trainer.IterAlpha = new float[] { 1f, 1f }; // length must equal the model's layer count
Throughput / diagnostics readouts
| Member | Purpose |
|---|---|
TokenBudget |
Current adaptive GPU per-dispatch token budget (climbs toward the card's throughput knee). |
CpuShare |
Current TCP-Reno-style count of bonus windows TrainBatchCoop hands the CPU. |
GpuWins / CpuWins |
Running counts of windows dispatched to each path, watch for a silent CPU fallback (GpuWins flat, CpuWins climbing). |
GpuMsTotal |
Cumulative GPU wall time across all batches. |
Console.WriteLine($"budget={trainer.TokenBudget} cpuShare={trainer.CpuShare} gpuWins={trainer.GpuWins} cpuWins={trainer.CpuWins}");
Relay / distributed-training helpers
| Member | Purpose |
|---|---|
GpuGradsAllPos(ex) |
Compute one shard's summed ALL-POSITIONS gradient + prediction count on the GPU, for a relay host/slave to merge across nodes. |
static GradBytes(g) |
Serialize a flat float[] gradient (Pairs order) as the canonical double-stream wire format the distributed relay uses. |
var (shardGrads, shardLossSum, shardCount) = trainer.GpuGradsAllPos(new List<int[]> { new[] { 1, 2, 3, 4, 5 } });
byte[] wire = GpuHoloTrainer.GradBytes(shardGrads);
GpuHoloModel: the low-level engine
The lower-level forward/backward engine GpuHoloTrainer wraps. Use it directly only if you need gradients/logits
without the trainer's batching, length-bucketing, or CPU-coop logic (e.g. a custom relay host, a research harness).
Construction, params, lifecycle
public GpuHoloModel(byte[] serialized) // from HoloFormer.Serialize()
Throws InvalidOperationException if no accelerator is available at all, or if d is odd. Throws
NotSupportedException if the serialized model uses an architecture flag this GPU path doesn't implement
(bindFfn:true, normalize:false, unitary:true, or any unrecognized flag bit), this fails loudly at
construction rather than silently computing the wrong math.
| Member | Purpose |
|---|---|
MaxContext |
The model's max context length. |
UpdateParams(serialized) |
Re-upload ALL params from a fresh HoloFormer.Serialize() (after a CPU-side weight change). |
UpdateTrainable(serialized) |
Faster re-upload of just the trainable params from HoloFormer.SerializeTrainable(), skipping the (unchanged) frozen embedding. |
Dispose() |
Frees all device buffers (params, grad accumulators, Adam moments, EVE probe state). |
using var gpuModel = new GpuHoloModel(model.Serialize());
int maxCtx = gpuModel.MaxContext;
gpuModel.UpdateParams(model.Serialize());
gpuModel.UpdateTrainable(model.SerializeTrainable());
// ... gpuModel.Dispose() when done, or `using`
Forward / inference
| Member | Purpose |
|---|---|
Forward(tokens) |
Batch forward: int[][] (each row ≤ MaxContext) → logits[B][V] at each example's last fed position. |
StackIterForward(tokens, K, alpha) |
Forward-only PER-LAYER weight-tied K-iteration inference, the serve-time mirror of StackIterBackward's forward. alpha per-layer, length must equal layer count. |
float[][] fwd = gpuModel.Forward(new[] { new[] { 1, 2, 3 } });
float[][] stackFwd = gpuModel.StackIterForward(new[] { new[] { 1, 2, 3 } }, K: 2, alpha: new float[] { 1f, 1f });
Backward / training
All backward methods return flat gradients in "Pairs order" (Emb, Pos, C, then per-layer 7 banks), the same
layout as HoloFormer.SerializeGradient.
| Member | Purpose |
|---|---|
Backward(tokens, targets) |
One forward+backward over a batch (single final-position target each). Returns (grads, meanLoss). |
IterBackward(tokens, targets, iters, alpha) |
Whole-STACK weight-tied iteration backward. L=1 models only, throws NotSupportedException otherwise. alpha is a plain scalar here. |
StackIterBackward(tokens, targets, K, alpha) |
PER-LAYER weight-tied K-iteration backward, works for any layer count, the one to use for L>1 depth. alpha per-layer. |
StackIterBackward(tokens, targets, K, alpha, out layerOutNormSum) |
ADDITIVE overload: same as above plus each layer's K-iterated output norm (summed over the batch), feeds the ADAM & EVE directional probe. |
StackIterBackwardAllPos(seqs, scoreP, K, alpha) |
ALL-POSITIONS variant: one forward per sequence, loss scored at the last scoreP transitions. Returns (grads, lossSum, count). Sequences up to MaxContext+1 tokens score whole; longer throws ArgumentException. |
StackIterBackwardAllPos(seqs, scoreP, K, alpha, out layerOutNormSum) |
ADDITIVE overload, same norm-capture contract as StackIterBackward's. |
ThinkBackward(tokens, target, nThoughts) |
Prompt + N latent "thought" steps, backprop through the recurrence. B=1, L=1 only. |
var alpha = new float[] { 1f, 1f }; // length == layer count (2 here)
var (grads, bwdLoss) = gpuModel.Backward(new[] { new[] { 1, 2, 3 } }, new[] { 4 });
var (stackGrads, stackLoss) = gpuModel.StackIterBackward(new[] { new[] { 1, 2, 3 } }, new[] { 4 }, K: 2, alpha: alpha);
var (stackGrads2, stackLoss2) = gpuModel.StackIterBackward(new[] { new[] { 1, 2, 3 } }, new[] { 4 }, K: 2, alpha: alpha, out var layerOutNormSum);
var (apGrads, apLossSum, apCount) = gpuModel.StackIterBackwardAllPos(new[] { new[] { 1, 2, 3, 4, 5 } }, scoreP: 2, K: 2, alpha: alpha);
// L=1-only methods need an L=1 model:
var model1 = new HoloFormer(vocab: 16, shifts: 4, layers: 1, maxContext: 6, dModel: 8);
using var gpu1 = new GpuHoloModel(model1.Serialize());
var (iterGrads, iterLoss) = gpu1.IterBackward(new[] { new[] { 1, 2, 3 } }, new[] { 4 }, iters: 2, alpha: 0.5f);
var (thinkGrads, thinkLoss) = gpu1.ThinkBackward(new[] { 1, 2, 3 }, target: 4, nThoughts: 1);
Fused on-GPU Adam (model level)
The mechanism GpuHoloTrainer.FusedGpuAdam drives. Use these directly only if you're building a custom trainer.
| Member | Purpose |
|---|---|
BeginAccumulate() |
Arm on-device gradient accumulation (zeroes the accumulators); subsequent backward calls add into them and return empty host grads. |
AbortAccumulate() |
Disarm without stepping (e.g. a batch produced zero scored predictions). |
AdamStep(lr, scale, clip=0, b1=0.9, b2=0.999, eps=1e-8) |
One on-device Adam step over the accumulated grads. Returns false (batch DROPPED, nothing mutated) if the global grad-norm wasn't finite. |
SkippedSteps |
Running count of AdamStep calls that dropped a batch. |
AddHostGrad(flatPairsOrder) |
Add a host-computed gradient (e.g. CPU-coop over-length window) into the device accumulators. Requires accumulation armed. |
DownloadParams() |
Read current device params back as a flat float[] (Pairs order), full readback, use only at sync points. |
DownloadOptimizerState() |
Read the Adam m/v moments + step counter back to host, Pairs order, for an exact-resume checkpoint. |
UploadOptimizerState(m, v, t) |
Restore the Adam m/v moments + step counter from host arrays. Throws ArgumentException on a length mismatch. |
gpuModel.BeginAccumulate();
gpuModel.Backward(new[] { new[] { 1, 2, 3 } }, new[] { 4 }); // armed: grads land in the accumulators, not returned
bool stepped = gpuModel.AdamStep(lr: 1e-2, scale: 1.0, clip: 1.0);
long gpuSkipped = gpuModel.SkippedSteps;
float[] flatParams = gpuModel.DownloadParams();
var (m, v, t) = gpuModel.DownloadOptimizerState();
gpuModel.UploadOptimizerState(m, v, t);
ADAM & EVE (model level)
The pure gate math and the fused-Adam-with-gate step, live in production via the trainer-level knobs above
(GpuHoloTrainer.EveEnabled etc., see that section for the recommended way to use this); these are the
primitives underneath.
| Member | Purpose |
|---|---|
DefaultEveInterval (const 16) |
Default recompute cadence for UsableRange. |
UsableRange(eps=1e-3, eveInterval=16, forceRefresh=false) |
Codebook-derived target (floor, ceiling) range, self-widening as tokens differentiate, no hand-picked hyperparameter. Auto-refreshes every eveInterval calls. |
static EveGain(before, after, floor, ceiling, e=0.05, distanceScaled=false, inBoost=1.0) |
Pure gate-math: the symmetric push-pull gain for a candidate step, given the layer's norm before/after. |
static EveBandCapGain(before, after, ceiling) |
Pure gate-math: the hard ratcheting-ceiling gain (EveBandCap's formula), a first estimate only, see AdamStepEve's bisection correction. |
AdamStepEve(lr, scale, floorNorm, ceilNorm, stackK, alpha, nudge=0.05, distanceScaled=false, clip=0, b1=0.9, b2=0.999, eps=1e-8, gainCache=null, recompute=true, inBoost=1.0, bandCap=false) |
The fused Adam step WITH the per-layer gate applied. Requires a norm-capturing StackIterBackward/StackIterBackwardAllPos call earlier in the same accumulation window, throws InvalidOperationException otherwise. |
var (floor, ceiling) = gpuModel.UsableRange(eps: 1e-3);
double gain = GpuHoloModel.EveGain(before: floor * 2, after: floor * 1.5, floor: floor, ceiling: ceiling);
double bandGain = GpuHoloModel.EveBandCapGain(before: floor * 2, after: floor * 1.5, ceiling: ceiling);
gpuModel.BeginAccumulate();
gpuModel.StackIterBackward(new[] { new[] { 1, 2, 3 } }, new[] { 4 }, K: 2, alpha: alpha, out _); // seeds the probe
bool eveStepped = gpuModel.AdamStepEve(lr: 1e-2, scale: 1.0, floorNorm: floor, ceilNorm: ceiling, stackK: 2, alpha: alpha);
Preference (DPO) training
GPU log-probabilities and a signed-weight training step, at the same weight-tied depth the trainer trains at
(StackK / IterAlpha). The DPO loss math itself stays on the host (HoloFormer.Dpo in the core package); these
members supply the scores and apply the weighted gradient.
Member (on GpuHoloTrainer) |
Purpose |
|---|---|
SequenceLogProbs(seqs, scoreFrom) / SequenceLogProb(seq, scoreFrom) / SequenceLogProb(context, continuation) |
Exact log P of seq[scoreFrom..] given the prefix under the current policy weights (<= 0, input order). Forward only. Valid length is 2..MaxContext+1; the call throws otherwise, so left-truncate the prompt yourself. |
NewReference() |
A frozen GpuHoloModel holding the policy's current weights. Score it with ReferenceLogProbs; never train it; dispose it when the preference phase ends. |
ReferenceLogProbs(reference, seqs, scoreFrom) |
Reference log-probs at this trainer's depth. Compute once up front, they never change. |
TrainBatchAllPosWeighted(seqs, scoreFrom, weights, lr, scale) |
Each sequence contributes weights[i] * grad(NLL_i) (positive raises its log-prob, negative lowers it), summed, then ONE optimiser step with your scale (for DPO, the pair count). Returns the per-sequence unweighted NLL. Works in classic, fused and ADAM & EVE modes. A weight of 0 skips a sequence; all-zero weights take no step; a non-finite weight throws before anything runs. |
GpuHoloModel carries the matching low-level SequenceLogProbs(seqs, scoreFrom, K, alpha) and
StackIterBackwardAllPosWeighted(seqs, scoreFrom, weights, K, alpha). unitary models are refused, as everywhere on
the GPU path.
var prefModel = new HoloFormer(vocab: 16, shifts: 4, layers: 2, maxContext: 6, dModel: 8);
using var prefTrainer = new GpuHoloTrainer(prefModel);
prefTrainer.StackK = 2;
// Each sequence is prompt ++ answer; scoreFrom is where the answer starts.
var pair = new[] { new[] { 1, 2, 3, 4, 5 }, new[] { 1, 2, 3, 6, 7 } }; // chosen, rejected
var scoreFrom = new[] { 3, 3 };
double[] policyLogp = prefTrainer.SequenceLogProbs(pair, scoreFrom); // log P(answer | prompt), <= 0
using var reference = prefTrainer.NewReference(); // frozen copy of the current policy
double[] refLogp = prefTrainer.ReferenceLogProbs(reference, pair, scoreFrom);
// +1 raises the chosen answer's log-prob, -1 lowers the rejected one; scale = number of pairs
double[] nll = prefTrainer.TrainBatchAllPosWeighted(pair, scoreFrom, new[] { 1.0, -1.0 }, lr: 1e-3, scale: 1.0);
Coherence gates, rising memory and atom preference on the GPU
Each GPU twin reads its CPU model's switch live, so a switch set on the CPU model applies on the GPU. With a switch off, the kernels and their output are unchanged. All switches default to off.
- In-layer gate.
GpuHoloTrainer,NewSnapshot()andNewReference()readHoloFormer.AttentionCoherenceGateandAttentionCoherenceCfrom the trainer's CPU model. Supported:StackIterForward,StackIterBackward,StackIterBackwardAllPosand its weighted form,SequenceLogProbs, and the fused atom stack. Refused withNotSupportedException: the legacyForwardandBackward,IterBackward,ThinkBackward, Eve (EveEnabledon the trainer, andAdamStepEve), the per-atom path withFusedAtoms = false, and the last-position atom methods. - Atom memory gate.
AtomFieldGpu.MemoryCoherenceGateandMemoryCoherenceCforward to the CPU field. Works with holographic and dense locality. Molecules throwInvalidOperationException, and shards throwNotSupportedException. - Atom rising memory.
AtomFieldGpu.MemoryRiseAmplitude(site)reads the device amplitude. Works with holographic and dense locality. Molecules throwInvalidOperationException, and shards throwNotSupportedException. - Atom preference lane.
AtomFieldGpu.SequenceLogProb,SequenceLogProbsandTrainStepAllPositionsWeightedmirror the CPU lane. They need the fused atom stack.
Verification. The in-layer gate (InLayerGateGpuTests, 17 cases), the atom memory gate (AtomFieldGpuGateTests, 5, and AtomFieldGpuGateLocalityTests, 9), atom rising memory (AtomFieldGpuRiseTests, 14) and the atom preference lane (AtomFieldGpuPreferenceTests, 10) were verified on the ILGPU CPU accelerator only. None of them has run on CUDA. The CUDA runs on this package cover the Pleroma transforms, the Newton pass and the timing of the fused atom step.
Pleroma page transforms
Exact batched transforms for Phasor's Pleroma key band, on the GPU. A "page" is N residues mod a prime q (a
CompleteKeys key line); many pages are transformed in one call. The arithmetic is integer, so results are
BIT-identical to the CPU, not float-close. q is 2^61 - 1 or any prime below 2^40; N is 2..4096; w must have
order exactly N (the constructor throws ArgumentException otherwise). There is no Phasor dependency in this
package: for a Pleroma store, recover w as RawCells[1] of Pleroma.FromCounts(shape, e_1).
| Member | Purpose |
|---|---|
new PleromaPageTransform(q, w, n, backend = null) |
Backend null = auto: CUDA, else the ILGPU CPU accelerator, else Managed (plain .NET, no ILGPU). Backend reports the one in use. |
Forward(counts, pages) |
Signed counts to key-line cells (Phasor FromCounts). |
Inverse(cells, pages) |
Cells back to signed counts (Phasor Counts()). |
Dft(x, pages, inverse) |
The raw residue transform, no N^-1 and no signed lift. |
ChunkElements |
Elements per device chunk (default 2^24), bounds device memory. |
Not thread safe: call serially. The ILGPU CPU backend is a correctness vehicle, 0.03 to 0.5x scalar Phasor; the speed-up is on CUDA. Measured on an RTX A3000: N = 3150 over 10,000 pages in 88-118 ms, 12-43x scalar Phasor.
const ulong q = (1UL << 61) - 1;
const int n = 110; // page length (a divisor of q - 1)
static ulong ModPow(ulong a, ulong e, ulong m)
{
ulong r = 1;
for (; e > 0; e >>= 1, a = (ulong)((UInt128)a * a % m)) if ((e & 1) == 1) r = (ulong)((UInt128)r * a % m);
return r;
}
// w must have order exactly n: take a power of a generator candidate and let the constructor check it.
PleromaPageTransform? xform = null;
for (ulong g = 2; xform is null; g++)
{
try { xform = new PleromaPageTransform(q, ModPow(g, (q - 1) / n, q), n); }
catch (ArgumentException) { }
}
using (xform)
{
var counts = new long[3 * n]; // 3 pages of signed counts
counts[5] = 7; counts[n + 9] = -2; counts[2 * n + 1] = 1;
ulong[] cells = xform.Forward(counts, pages: 3); // counts -> key-line cells
long[] back = xform.Inverse(cells, pages: 3); // cells -> counts, exact
Console.WriteLine($"{xform.Backend} roundtrip exact: {back.AsSpan().SequenceEqual(counts)}");
}
PleromaNewtonGpu(vocab, radii) is the GPU twin of the Pleroma Cascade's Newton pass: Pass(sample, theta, wantH)
returns the summed loss (nats), the gradient and, on request, the exact Hessian of the solved operator over token
sequences (Loss(sample, theta) is the loss alone, for a line search). Gradient and Hessian are accumulated in fp64
from fp32 features, float-close to the fp64 CPU pass (relative error gate 1e-5). vocab is 2..110.
using var newton = new PleromaNewtonGpu(vocab: 27, radii: new[] { 0.5, 0.7, 0.85, 0.95 });
double[] theta = new double[newton.P]; // [Re K..., Im K...], 880 values for 4 radii
var sample = new[] { new[] { 1, 2, 3, 4, 5 } };
var (nllSum, gradient, hessian) = newton.Pass(sample, theta, wantH: true);
GpuOps: standalone kernel verify/bench
Static helpers with no model required, gradcheck/benchmark harnesses for the two kernels every other type here is built on (the relation-bank op, and the fused Adam kernel). Useful for a CI smoke test or a quick sanity check on a new machine.
| Member | Purpose |
|---|---|
VerifyRelBank(BT=4096, d=256, s=16, seed=1) |
Gradcheck + time the relation-bank forward kernel against the CPU double definition. Returns (worstErr, gpuMs, cpuMs). |
VerifyRelBankBackward(BT=512, d=256, s=16, seed=2) |
Gradcheck the relation-bank backward kernel (bank-grad + input-grad). Returns (worstBankGradErr, worstInputGradErr). |
VerifyAdam(n=65536, t=7, seed=3) |
Gradcheck the fused on-GPU Adam kernel, the SAME kernel GpuHoloModel.AdamStep/AdamStepEve run, against the CPU double definition. Returns (worstParamErr, worstMErr, worstVErr). |
var (worstRelBank, gpuMs, cpuMs) = GpuOps.VerifyRelBank(BT: 64, d: 16, s: 4);
var (worstBankGrad, worstInputGrad) = GpuOps.VerifyRelBankBackward(BT: 32, d: 16, s: 4);
var (worstParam, worstM, worstV) = GpuOps.VerifyAdam(n: 256, t: 3);
// all three worst-error values should be well under 1e-4 on real CUDA (fp32-vs-fp64 closeness)
Deprecated non-holo twin: GpuModel / GpuTrainer
[Obsolete], still builds, runs, and gradchecks, but gets no further development. This is the GPU twin of
the older softmax-attention AlgFormer core (not HoloFormer). Use GpuHoloModel/GpuHoloTrainer for anything
new; migrate existing callers when convenient.
| Member | Purpose |
|---|---|
GpuTrainer(AlgFormer cpu, int tokenBudget = 24576) |
Drop-in batch trainer, same shape as GpuHoloTrainer but for AlgFormer. CPU Adam only, no fused-Adam mode (that's holo-only, permanently). |
GpuTrainer.TrainBatch(batch, lr) |
Same contract as GpuHoloTrainer.TrainBatch. |
GpuModel(byte[] serialized) |
The low-level forward/backward engine GpuTrainer wraps. |
GpuModel.MaxContext / .Forward(tokens) / .Backward(tokens, targets) / .UpdateParams(serialized) / .UpdateTrainable(serialized) |
Same contracts as their GpuHoloModel equivalents (no StackIter/think/fused-Adam/EVE surface, none of that was ported here). |
#pragma warning disable CS0618 // acknowledge the deprecation warning for this example
var cpuAlg = new AlgFormer(vocab: 16, shifts: 4, layers: 2, maxContext: 6, dModel: 8);
using var oldTrainer = new GpuTrainer(cpuAlg);
double oldLoss = oldTrainer.TrainBatch(batch, lr: 5e-2);
using var oldModel = new GpuModel(cpuAlg.Serialize());
float[][] oldFwd = oldModel.Forward(new[] { new[] { 1, 2, 3 } });
var (oldGrads, oldBwdLoss) = oldModel.Backward(new[] { new[] { 1, 2, 3 } }, new[] { 4 });
#pragma warning restore CS0618
Maturity notes
- Classic path (
FusedGpuAdam = false, the default): production-proven, gradchecked against the CPU oracle, exercised by a live long-running trainer, with a drop-not-clip non-finite-gradient guard. - Fused Adam (
FusedGpuAdam = true): ALSO production-proven, it's what the live HoloEngine trains with, but it inverts weight authority to the GPU for the run (see Gotchas). - ADAM & EVE (
EveEnabled = true): LIVE IN PRODUCTION, this package ships it default OFF, but PrismStudio's HoloEngine has run it as the active optimizer path (viaFusedGpuAdam) since 2026-09-24. Gradchecked against the CPU oracle in isolation (finite-difference, production shape) in addition to the live run. - Known GPU/CPU architecture gaps fail LOUDLY (
NotSupportedExceptionat construction) rather than silently computing the wrong thing: aHoloFormerbuilt withbindFfn:true,normalize:false, orunitary:trueis refused byGpuHoloModel/GpuHoloTrainer: those three axes are not implemented on the GPU path. - Nothing in this package is license-gated or tiered; every capability above is available with no key.
License
Proprietary, this package ships the compiled library only; see LICENSE for the full terms. Installing
and using unmodified copies for internal evaluation and non-commercial development or testing is licensed;
commercial, production, or revenue-generating use requires a separate commercial licence from the owner.
No feature on this page is gated behind a tier or a licence key, every capability described works
identically with or without one. Copyright (c) 2026 Dongyang Stephen Chen, trading as Evaluated
Applications. All rights reserved.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- EvaluatedApplications.AlgFormer (>= 4.0.1)
- EvaluatedApplications.EvalApp (>= 6.0.1)
- ILGPU (>= 1.5.1)
- ILGPU.Algorithms (>= 1.5.1)
-
net8.0
- EvaluatedApplications.AlgFormer (>= 4.0.1)
- EvaluatedApplications.EvalApp (>= 6.0.1)
- ILGPU (>= 1.5.1)
- ILGPU.Algorithms (>= 1.5.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.16.1 | 62 | 11/10/2026 |
| 1.16.0 | 66 | 11/9/2026 |
| 1.13.0 | 91 | 11/3/2026 |
| 1.12.0 | 125 | 10/8/2026 |
| 1.11.0 | 116 | 10/4/2026 |
| 1.10.7 | 120 | 10/4/2026 |
| 1.10.6 | 112 | 10/3/2026 |
| 1.10.5 | 122 | 10/3/2026 |
| 1.10.4 | 110 | 10/3/2026 |
| 1.10.3 | 112 | 10/3/2026 |
| 1.10.2 | 114 | 10/2/2026 |
| 1.10.1 | 111 | 10/2/2026 |
| 1.10.0 | 106 | 9/24/2026 |
| 1.9.0 | 108 | 9/24/2026 |
| 1.8.0 | 107 | 9/24/2026 |
| 1.7.0 | 118 | 9/23/2026 |
| 1.6.0 | 111 | 9/23/2026 |
| 1.5.3 | 107 | 9/22/2026 |
| 1.5.2 | 109 | 9/20/2026 |
| 1.5.1 | 111 | 9/20/2026 |