021 — device-resident cuML on the original five tasks

015 timed cuML on a NumPy array, so those cells include the host-to-device copy. 020 changed _worker_cuml so the timer starts only after the samples and the shared random-row centers are CuPy arrays, and it measured that protocol on k256-d128 only. This iteration reruns the other five tasks under the same contract. Array-API, stock scikit-learn, and cakedev0 cells are unchanged and stay in 015 and 020.

The full result set is results.json. Each task's .npy was deleted after its three seeds so the host kept its free-disk headroom.

Setup

Full fit

Time in seconds, mean ± sample standard deviation. The 015 column is the published seed mean with the copy inside the timer.

init k3-d1000 k17-d180 k100-d32 k550-d6 k3000-d2
greedy, 015 7.18 2.50 0.98 1.01 1.20
greedy, device-resident 3.849 ± 0.013 0.937 ± 0.001 0.683 ± 0.003 0.876 ± 0.003 1.064 ± 0.004
scalable, 015 6.38 ± 1.67 2.39 0.73 0.64 1.16
scalable, device-resident 3.238 ± 1.673 0.831 ± 0.021 0.440 ± 0.001 0.515 ± 0.001 1.065 ± 0.007

The 015 means are slower by 3.33 / 1.56 / 0.30 / 0.13 / 0.14 s on the greedy fits and by 3.14 / 1.56 / 0.29 / 0.13 / 0.10 s on the scalable fits. The gaps follow the input size.

k3-d1000 scalable seed 1 stops after 2 iterations (1.306 s, inertia 999.974). Seeds 0 and 2 run all 12 iterations (4.201 s and 4.206 s, inertia 999.320 and 998.869). A separate process of seed 1 stops after 2 iterations again, at 1.298 s. The mean includes that early stop, as the 015 mean of 6.38 ± 1.67 s did. The two 12-iteration seeds average 4.20 s.

Against the 015 array-API GPU rows, which were already device-resident:

Lloyd from the same random rows

init k3-d1000 k17-d180 k100-d32 k550-d6 k3000-d2
cuML, 015 6.88 2.12 0.54 0.35 0.32
cuML, device-resident 3.694 ± 0.023 0.525 ± 0.004 0.202 ± 0.001 0.198 ± 0.001 0.160 ± 0.001
fastest array API in 015 0.89 0.63 0.39 0.42 0.58

The 015 Lloyd means are slower by 3.19 / 1.59 / 0.34 / 0.15 / 0.16 s. Removing the copy reverses the ranking at 17 and 100 clusters: cuML is now 0.53 s against 0.63 s, and 0.20 s against 0.39 s. It was already ahead at 550 and 3000 clusters and is now 0.20 s and 0.16 s. At 3 clusters Torch CUDA remains faster (0.89 s against 3.69 s). The copy was about half of the old 6.88 s cell; the remaining gap is the Lloyd kernel.

Quality and memory

Greedy and shared-start inertias on k3-d1000, k17-d180, and k100-d32 agree within 0.11%. On k550-d6, scalable is 0.13% below greedy and the shared start is 0.21% above it. On k3000-d2, scalable is 5.4% above greedy, and the shared start is 47% above greedy because cuML keeps empty centers. That shared-start gap against the other implementations was 7% in 015 and is a quality result, not a placement result.

nvidia-smi growth above the preallocated input, greedy fits: 54 MiB, 136 MiB, 98 MiB, 56 MiB, and 14 MiB. The 3.8 GiB cuML figure in 015 for k3-d1000 included allocating the device copy of the 3.54 GiB input.

Conclusion

The five cuML columns in 015 were the cells affected by the placement change, and they are replaced by this run. k256-d128 was already device-resident in 020. Initialization-only cuML timings in 015 already copied to the device before the timer and are left as published.

With every GPU contender starting from device-resident data, cuML's shared-start Lloyd is faster from 17 clusters up, and cuML scalable is the fastest full fit from 17 clusters up. The array API remains faster at 3 clusters on both Lloyd and the greedy full fit. The wide-task gap is smaller than 015 reported, and it is still a kernel gap.

Previous: balanced clusters and features. Index: journal.