Lloyd k-means in the Python array API

What this PR explores

This experiment studies nearest-centroid assignment, Lloyd updates, empty clusters, and centroid initialization through the Python array API. The eager implementation runs with PyTorch on CPU, CUDA, and XPU, with CuPy on CUDA, and with dpnp on a Level Zero GPU. Comparisons cover stock scikit-learn, scikit-learn with k-means++ performance patches, Cython, and cuML.

The journal progresses from kernel-fusion probes to bounded-memory tiled assignment, full fits, repeated-seed and shared-start comparisons, empty-center relocation, and greedy versus scalable initialization. The current six-task mix spans 3 to 3000 clusters, 2 to 1000 features, and 135000 to 2100000 samples, including a balanced 256-cluster, 128-feature case. Runs use float32, eager execution, TF32 disabled, three seeds, and a 60-second worker limit.

Latest results

023 adds the portable array-API path on dpnp GPU arrays to the 022 Arc B390 measurements. 022 holds PyTorch XPU (native and one-hot), PyTorch CPU, stock scikit-learn 1.9.1, and cakedev0. CuPy and cuML are absent on this host.

Main conclusions:

Journal