Benchmarks#

This benchmark is based on PyCave’s benchmarking, where they evaluated the runtime performance of TorchGMM by running an exhaustive set of experiments to compare against the implementation found in scikit-learn. Evaluations are run at varying dataset sizes.

All benchmarks are run on an instance with a Intel Xeon E5-2630 v4 CPU (2.2 GHz). They use at most 4 cores and 60 GiB of memory. Also, there is a single GeForce GTX 1080 Ti GPU (11 GiB memory) available. For the performance measures, each benchmark is run at least 5 times.

Gaussian Mixture#

Setup#

For measuring the performance of fitting a Gaussian mixture model, they fix the number of iterations after initialization to 100 to not measure any variances in the convergence criterion. For initialization, they further set the known means that were used to generate data to not run into issues of degenerate covariance matrices. Thus, all benchmarks essentially measure the performance after K-means initialization has been run. Benchmarks for K-means itself are listed below.

Results#

Scikit-Learn

TorchGMM CPU (full)

TorchGMM CPU (batches)

TorchGMM GPU (full)

TorchGMM GPU (batches)

[10k, 8] -> 4

352 ms

649 ms

3.9 s

358 ms

3.6 s

[100k, 32] -> 16

18.4 s

4.3 s

10.0 s

527 ms

3.9 s

[1M, 64] -> 64

730 s

196 s

284 s

7.7 s

15.3 s

Training Duration for Diagonal Covariance ([num_datapoints, num_features] -> num_components)

Scikit-Learn

TorchGMM CPU (full)

TorchGMM CPU (batches)

TorchGMM GPU (full)

TorchGMM GPU (batches)

[10k, 8] -> 4

699 ms

570 ms

3.6 s

356 ms

3.3 s

[100k, 32] -> 16

72.2 s

12.1 s

16.1 s

919 ms

3.8 s

[1M, 64] -> 64

63.4 s

Training Duration for Tied Covariance ([num_datapoints, num_features] -> num_components)

Scikit-Learn

TorchGMM CPU (full)

TorchGMM CPU (batches)

TorchGMM GPU (full)

TorchGMM GPU (batches)

[10k, 8] -> 4

1.1 s

679 ms

4.1 s

648 ms

4.4 s

[100k, 32] -> 16

110 s

13.5 s

21.2 s

2.4 s

7.8 s

Training Duration for Full Covariance ([num_datapoints, num_features] -> num_components)

Summary#

TorchGMM’s implementation of the Gaussian mixture model is markedly more efficient than the one found in scikit-learn. Even on the CPU, TorchGMM outperforms scikit-learn significantly at a 100k datapoints already. When moving to the GPU, however, TorchGMM unfolds its full potential and yields speed ups at around 100x. For larger datasets, mini-batch training is the only alternative. TorchGMM fully supports that while the training is approximately twice as large as when training using the full data. The reason for this is that the M-step of the EM algorithm needs to be split across epochs, which, in turn, requires to replay the E-step.

K-Means#

Setup#

For the scikit-learn implementation, they use Lloyd’s algorithm instead of Elkan’s algorithm to have a useful comparison with TorchGMM (which implements Lloyd’s algorithm).

Further, they fix the number of iterations after initialization to 100 to not measure any variances in the convergence criterion.

Results#

Scikit-Learn

TorchGMM CPU (full)

TorchGMM CPU (batches)

TorchGMM GPU (full)

TorchGMM GPU (batches)

[10k, 8] -> 4

13 ms

412 ms

797 ms

387 ms

2.1 s

[100k, 32] -> 16

311 ms

2.1 s

3.4 s

707 ms

2.5 s

[1M, 64] -> 64

10.0 s

73.6 s

58.1 s

8.2 s

10.0 s

[10M, 128] -> 128

254 s

133 s

Training Duration for Random Initialization ([num_datapoints, num_features] -> num_clusters)

Scikit-Learn

TorchGMM CPU (full)

TorchGMM CPU (batches)

TorchGMM GPU (full)

TorchGMM GPU (batches)

[10k, 8] -> 4

15 ms

170 ms

930 ms

431 ms

2.4 s

[100k, 32] -> 16

542 ms

2.3 s

4.3 s

840 ms

3.2 s

[1M, 64] -> 64

25.3 s

93.4 s

83.7 s

13.1 s

17.1 s

[10M, 128] -> 128

827 s

369 s

Training Duration for K-Means++ Initialization ([num_datapoints, num_features] -> num_clusters)

Summary#

As it turns out, it is really hard to outperform the implementation found in scikit-learn. Especially if little data is available, the overhead of PyTorch and PyTorch Lightning renders TorchGMM comparatively slow. However, as more data is available, TorchGMM starts to become relatively faster and, when leveraging the GPU, it finally outperforms scikit-learn for a dataset size of 1M datapoints. Nonetheless, the improvement is marginal.