Engineering story · Inference Fabric

Two-means as a measuring instrument

Exactly three Lloyd iterations, seeded at the first and last member, as the fixed definition behind clustering tendency, fragmentation, sub-cluster count and silhouette

CUDA C++ kernelsInference FabricDeterministic metrics
One cluster · members in order, first and last seeded
Then stop · no convergence test the same split, every run, on GPU and CPU
3Lloyd iterations, by definition
Tendency · fragmentation · sub-clusters · silhouette
  • 4cluster metrics read from one fixed split
  • 0.5Mmembers per second, about half a million, linear in size
  • 1.2 msor less for the silhouette on the clusters it meets

Does this cluster want to be two clusters? The usual answer is to run k-means with k equal to two and look at the result, and the usual problem is that k-means is an optimiser: it runs until it converges, converges somewhere different depending on its seeds, and gives a different answer on a different day. I wanted the answer to be a metric, which means a fixed procedure with a fixed result. So the two-means split in my engine is defined as a measuring instrument, and four metrics read from it.

The fixed procedure

One block per cluster. A first pass computes the single-centroid inertia, the sum of squared distances to the cluster's own centroid. Two centroids are then seeded at the first and the last member of the cluster, deterministically, and exactly three Lloyd iterations follow. Three iterations is the definition; there is no convergence test.

One block per cluster
Inertia, one centroidSeed first and last memberThree Lloyd iterationsStop
Each iteration
Classify: one byte per member, grid-strideReduce counts and inertiaUpdate centroids, one thread per dimension
No atomics anywhere and about 12 KB of shared memory per block; run time grows linearly with the member count.

Four metrics from one split

Every metric is defined in terms of that one split, so all four agree on which members sit on which side. The sub-cluster count is derived from the other readings and how balanced the split is.

One split · four readings
Clustering tendencyHow much a split helpsOne minus two-centroid inertia over one-centroid inertia.
Fragmentation indexHow far apart the halves sitCentroid separation against the variance inside each half.
Sub-cluster countBetween one and two
A cluster can read as one and a half instead of being forced to an integer.
SilhouetteOwn side against the other sideMean distance to each side per member, standard score rescaled to the unit interval.

Silhouette without the square roots

The silhouette kernel is tiled over the split assignments and accumulates squared-distance sums and counts per member, same side and other side, with no atomics and the square root deferred to the finalize. Degenerate cases have fixed answers: a singleton or a cluster whose split put everyone on one side scores a neutral zero rather than a division error. A second finalize writes the per-member silhouette alongside the cluster value for analysis.

One member · two running sums
Same sideΣ d²Other sideΣ d²Square rootfinalize
Singleton or one-sided split
other sideneutral zeroown side
Illustrative proportions.

Why fixed beats converged

Three fixed iterations from fixed seeds give the same number for the same cluster every time, on the GPU and in the CPU reference, which is what makes the tendency score comparable across a corpus and across runs. The pressure model that decides whether to split a cluster reads this score, and a decision rule needs an instrument.

k-means run to convergence · same cluster
Seeds AvariesSeeds BvariesSeeds Cvaries

A better split each time, and a different number each time.

The instrument · same cluster
GPU, run 1sameGPU, run 2sameCPU referencesame

Fixed seeds, three iterations, written-down edge cases.

Illustrative bar lengths: the point is the spread, not the values.

A converged k-means gives a better split and a worse metric.

What this demonstrates

Turning an algorithm into a measurement by fixing its degrees of freedom: seeds, iterations and edge cases written down, and four metrics defined in terms of the result.

I set the fixed procedure and the metric definitions; the kernels and references were implemented by AI coding agents, a mix of frontier and open-source models, under my governance system.