digit histogram performance benchmarks#

This example benchmarks the digit histogram primitive (the upfront histogram of every radix digit place of a key buffer, as used by the Onesweep radix sort) for the different digit sizes available in Shamrock, on 3 key distributions:

  • zeros : every key is 0, so every digit place of every key lands in the same bin (worst case for the atomic contention on the histogram bins)

  • shuffled iota : a random permutation of 0 .. N-1, the low digit places are uniform while the high ones are concentrated on the few lowest bins

  • random : uniformly distributed keys over the full u32 range, every digit place is uniform

17 import time
18
19 import matplotlib.pyplot as plt
20 import numpy as np
21 from shamrock.utils.plot import make_std_bench_plot
22
23 import shamrock
24
25 # If we use the shamrock executable to run this script instead of the python interpreter,
26 # we should not initialize the system as the shamrock executable needs to handle specific MPI logic
27 if not shamrock.sys.is_initialized():
28     shamrock.change_loglevel(1)
29     shamrock.sys.init("0:0")

Use shamrock documentation style for matplotlib

35 shamrock.matplotlib.set_shamrock_mpl_style()

Digit sizes (in bits) supported by the digit histogram

39 radix_bits_list = [1, 2, 4, 8]

Key distributions to benchmark

43 key_cases = ["zeros", "shuffled iota", "random"]
44
45
46 def make_keys(case, N, seed=111):
47     if case == "zeros":
48         keys = shamrock.backends.DeviceBuffer_u32()
49         keys.resize(N)
50         keys.fill(0)
51         return keys
52     elif case == "shuffled iota":
53         rng = np.random.default_rng(seed)
54         keys = shamrock.backends.DeviceBuffer_u32()
55         keys.resize(N)
56         keys.copy_from_stdvec(rng.permutation(N).astype(np.uint32).tolist())
57         return keys
58     elif case == "random":
59         return shamrock.algs.mock_buffer_u32(seed, N, 0, 2**32 - 1)
60     else:
61         raise ValueError(f"unknown key case {case}")

Check the result against numpy

66 def reference_digit_histogram(keys, radix_bits):
67     keys_np = np.array(keys.copy_to_stdvec(), dtype=np.uint64)
68     nbuckets = 2**radix_bits
69     npasses = 32 // radix_bits
70     return np.concatenate(
71         [
72             np.bincount((keys_np >> (p * radix_bits)) & (nbuckets - 1), minlength=nbuckets)
73             for p in range(npasses)
74         ]
75     )
76
77
78 def compute_digit_histogram(keys, radix_bits):
79     N = keys.get_size()
80     return np.array(shamrock.algs.digit_histogram(keys, radix_bits, N).copy_to_stdvec())
81
82
83 for case in key_cases:
84     keys = make_keys(case, 100003)
85     for radix_bits in radix_bits_list:
86         ok = np.array_equal(
87             compute_digit_histogram(keys, radix_bits), reference_digit_histogram(keys, radix_bits)
88         )
89         print(f"{case:>13s}, radix_bits={radix_bits} : result matches numpy = {ok}")
        zeros, radix_bits=1 : result matches numpy = True
        zeros, radix_bits=2 : result matches numpy = True
        zeros, radix_bits=4 : result matches numpy = True
        zeros, radix_bits=8 : result matches numpy = True
shuffled iota, radix_bits=1 : result matches numpy = True
shuffled iota, radix_bits=2 : result matches numpy = True
shuffled iota, radix_bits=4 : result matches numpy = True
shuffled iota, radix_bits=8 : result matches numpy = True
       random, radix_bits=1 : result matches numpy = True
       random, radix_bits=2 : result matches numpy = True
       random, radix_bits=4 : result matches numpy = True
       random, radix_bits=8 : result matches numpy = True

Main benchmark function

 94 def benchmark_u32(keys, radix_bits, nb_repeat=10, max_cumulated_time=2.0):
 95     N = keys.get_size()
 96
 97     times = []
 98     cumulated_time = 0.0
 99     for _ in range(nb_repeat):
100         t = shamrock.algs.benchmark_digit_histogram(keys, radix_bits, N)
101         times.append(t)
102         cumulated_time += t
103
104         if cumulated_time > max_cumulated_time:
105             break
106     return min(times), max(times), sum(times) / len(times)

Run the performance test for all parameters (the keys of a given case and size are generated once and reused for every digit size)

112 def run_performance_sweep():
113     # logspace as array, deliberately not restricted to powers of 2
114     particle_counts = np.logspace(2, 7, 20).astype(int).tolist()
115
116     results = {case: {radix_bits: [] for radix_bits in radix_bits_list} for case in key_cases}
117
118     print(f"Particle counts: {particle_counts}")
119
120     total_runs = len(particle_counts)
121
122     for current_run, N in enumerate(particle_counts, start=1):
123         for case in key_cases:
124             keys = make_keys(case, N)
125             for radix_bits in radix_bits_list:
126                 print(
127                     f"[{current_run:2d}/{total_runs}] Running N={N:8d}, {case:>13s}, "
128                     f"radix_bits={radix_bits}...",
129                     end=" ",
130                 )
131
132                 start_time = time.time()
133                 min_time, max_time, mean_time = benchmark_u32(keys, radix_bits)
134                 results[case][radix_bits].append(min_time)
135                 elapsed = time.time() - start_time
136
137                 print(f"mean={mean_time:.3e}s (took {elapsed:.1f}s)")
138
139     return particle_counts, results

Run the performance benchmarks for all key distributions and digit sizes

145 particle_counts, results = run_performance_sweep()
Particle counts: [100, 183, 335, 615, 1128, 2069, 3792, 6951, 12742, 23357, 42813, 78475, 143844, 263665, 483293, 885866, 1623776, 2976351, 5455594, 10000000]
[ 1/20] Running N=     100,         zeros, radix_bits=1... mean=1.035e-04s (took 0.0s)
[ 1/20] Running N=     100,         zeros, radix_bits=2... mean=8.054e-05s (took 0.0s)
[ 1/20] Running N=     100,         zeros, radix_bits=4... mean=8.142e-05s (took 0.0s)
[ 1/20] Running N=     100,         zeros, radix_bits=8... mean=8.446e-05s (took 0.0s)
[ 1/20] Running N=     100, shuffled iota, radix_bits=1... mean=8.398e-05s (took 0.0s)
[ 1/20] Running N=     100, shuffled iota, radix_bits=2... mean=7.665e-05s (took 0.0s)
[ 1/20] Running N=     100, shuffled iota, radix_bits=4... mean=7.385e-05s (took 0.0s)
[ 1/20] Running N=     100, shuffled iota, radix_bits=8... mean=7.459e-05s (took 0.0s)
[ 1/20] Running N=     100,        random, radix_bits=1... mean=1.124e-04s (took 0.0s)
[ 1/20] Running N=     100,        random, radix_bits=2... mean=1.036e-04s (took 0.0s)
[ 1/20] Running N=     100,        random, radix_bits=4... mean=1.648e-04s (took 0.0s)
[ 1/20] Running N=     100,        random, radix_bits=8... mean=1.392e-04s (took 0.0s)
[ 2/20] Running N=     183,         zeros, radix_bits=1... mean=1.168e-04s (took 0.0s)
[ 2/20] Running N=     183,         zeros, radix_bits=2... mean=1.057e-04s (took 0.0s)
[ 2/20] Running N=     183,         zeros, radix_bits=4... mean=1.028e-04s (took 0.0s)
[ 2/20] Running N=     183,         zeros, radix_bits=8... mean=1.012e-04s (took 0.0s)
[ 2/20] Running N=     183, shuffled iota, radix_bits=1... mean=9.921e-05s (took 0.0s)
[ 2/20] Running N=     183, shuffled iota, radix_bits=2... mean=7.844e-05s (took 0.0s)
[ 2/20] Running N=     183, shuffled iota, radix_bits=4... mean=6.928e-05s (took 0.0s)
[ 2/20] Running N=     183, shuffled iota, radix_bits=8... mean=6.917e-05s (took 0.0s)
[ 2/20] Running N=     183,        random, radix_bits=1... mean=9.872e-05s (took 0.0s)
[ 2/20] Running N=     183,        random, radix_bits=2... mean=7.214e-05s (took 0.0s)
[ 2/20] Running N=     183,        random, radix_bits=4... mean=6.812e-05s (took 0.0s)
[ 2/20] Running N=     183,        random, radix_bits=8... mean=7.009e-05s (took 0.0s)
[ 3/20] Running N=     335,         zeros, radix_bits=1... mean=9.180e-05s (took 0.0s)
[ 3/20] Running N=     335,         zeros, radix_bits=2... mean=7.743e-05s (took 0.0s)
[ 3/20] Running N=     335,         zeros, radix_bits=4... mean=7.313e-05s (took 0.0s)
[ 3/20] Running N=     335,         zeros, radix_bits=8... mean=6.938e-05s (took 0.0s)
[ 3/20] Running N=     335, shuffled iota, radix_bits=1... mean=9.615e-05s (took 0.0s)
[ 3/20] Running N=     335, shuffled iota, radix_bits=2... mean=8.004e-05s (took 0.0s)
[ 3/20] Running N=     335, shuffled iota, radix_bits=4... mean=6.844e-05s (took 0.0s)
[ 3/20] Running N=     335, shuffled iota, radix_bits=8... mean=7.039e-05s (took 0.0s)
[ 3/20] Running N=     335,        random, radix_bits=1... mean=9.862e-05s (took 0.0s)
[ 3/20] Running N=     335,        random, radix_bits=2... mean=8.207e-05s (took 0.0s)
[ 3/20] Running N=     335,        random, radix_bits=4... mean=7.697e-05s (took 0.0s)
[ 3/20] Running N=     335,        random, radix_bits=8... mean=7.266e-05s (took 0.0s)
[ 4/20] Running N=     615,         zeros, radix_bits=1... mean=1.172e-04s (took 0.0s)
[ 4/20] Running N=     615,         zeros, radix_bits=2... mean=9.222e-05s (took 0.0s)
[ 4/20] Running N=     615,         zeros, radix_bits=4... mean=7.982e-05s (took 0.0s)
[ 4/20] Running N=     615,         zeros, radix_bits=8... mean=7.127e-05s (took 0.0s)
[ 4/20] Running N=     615, shuffled iota, radix_bits=1... mean=1.192e-04s (took 0.0s)
[ 4/20] Running N=     615, shuffled iota, radix_bits=2... mean=9.028e-05s (took 0.0s)
[ 4/20] Running N=     615, shuffled iota, radix_bits=4... mean=7.720e-05s (took 0.0s)
[ 4/20] Running N=     615, shuffled iota, radix_bits=8... mean=7.247e-05s (took 0.0s)
[ 4/20] Running N=     615,        random, radix_bits=1... mean=1.173e-04s (took 0.0s)
[ 4/20] Running N=     615,        random, radix_bits=2... mean=9.419e-05s (took 0.0s)
[ 4/20] Running N=     615,        random, radix_bits=4... mean=7.846e-05s (took 0.0s)
[ 4/20] Running N=     615,        random, radix_bits=8... mean=7.432e-05s (took 0.0s)
[ 5/20] Running N=    1128,         zeros, radix_bits=1... mean=1.875e-04s (took 0.0s)
[ 5/20] Running N=    1128,         zeros, radix_bits=2... mean=1.200e-04s (took 0.0s)
[ 5/20] Running N=    1128,         zeros, radix_bits=4... mean=9.724e-05s (took 0.0s)
[ 5/20] Running N=    1128,         zeros, radix_bits=8... mean=8.528e-05s (took 0.0s)
[ 5/20] Running N=    1128, shuffled iota, radix_bits=1... mean=1.664e-04s (took 0.0s)
[ 5/20] Running N=    1128, shuffled iota, radix_bits=2... mean=1.153e-04s (took 0.0s)
[ 5/20] Running N=    1128, shuffled iota, radix_bits=4... mean=9.374e-05s (took 0.0s)
[ 5/20] Running N=    1128, shuffled iota, radix_bits=8... mean=7.986e-05s (took 0.0s)
[ 5/20] Running N=    1128,        random, radix_bits=1... mean=1.582e-04s (took 0.0s)
[ 5/20] Running N=    1128,        random, radix_bits=2... mean=1.131e-04s (took 0.0s)
[ 5/20] Running N=    1128,        random, radix_bits=4... mean=8.550e-05s (took 0.0s)
[ 5/20] Running N=    1128,        random, radix_bits=8... mean=7.662e-05s (took 0.0s)
[ 6/20] Running N=    2069,         zeros, radix_bits=1... mean=2.374e-04s (took 0.0s)
[ 6/20] Running N=    2069,         zeros, radix_bits=2... mean=1.529e-04s (took 0.0s)
[ 6/20] Running N=    2069,         zeros, radix_bits=4... mean=1.073e-04s (took 0.0s)
[ 6/20] Running N=    2069,         zeros, radix_bits=8... mean=1.084e-04s (took 0.0s)
[ 6/20] Running N=    2069, shuffled iota, radix_bits=1... mean=2.374e-04s (took 0.0s)
[ 6/20] Running N=    2069, shuffled iota, radix_bits=2... mean=1.537e-04s (took 0.0s)
[ 6/20] Running N=    2069, shuffled iota, radix_bits=4... mean=1.068e-04s (took 0.0s)
[ 6/20] Running N=    2069, shuffled iota, radix_bits=8... mean=8.559e-05s (took 0.0s)
[ 6/20] Running N=    2069,        random, radix_bits=1... mean=2.496e-04s (took 0.0s)
[ 6/20] Running N=    2069,        random, radix_bits=2... mean=1.564e-04s (took 0.0s)
[ 6/20] Running N=    2069,        random, radix_bits=4... mean=1.115e-04s (took 0.0s)
[ 6/20] Running N=    2069,        random, radix_bits=8... mean=8.760e-05s (took 0.0s)
[ 7/20] Running N=    3792,         zeros, radix_bits=1... mean=2.378e-04s (took 0.0s)
[ 7/20] Running N=    3792,         zeros, radix_bits=2... mean=1.566e-04s (took 0.0s)
[ 7/20] Running N=    3792,         zeros, radix_bits=4... mean=1.075e-04s (took 0.0s)
[ 7/20] Running N=    3792,         zeros, radix_bits=8... mean=1.088e-04s (took 0.0s)
[ 7/20] Running N=    3792, shuffled iota, radix_bits=1... mean=2.436e-04s (took 0.0s)
[ 7/20] Running N=    3792, shuffled iota, radix_bits=2... mean=1.538e-04s (took 0.0s)
[ 7/20] Running N=    3792, shuffled iota, radix_bits=4... mean=1.033e-04s (took 0.0s)
[ 7/20] Running N=    3792, shuffled iota, radix_bits=8... mean=8.761e-05s (took 0.0s)
[ 7/20] Running N=    3792,        random, radix_bits=1... mean=2.347e-04s (took 0.0s)
[ 7/20] Running N=    3792,        random, radix_bits=2... mean=1.544e-04s (took 0.0s)
[ 7/20] Running N=    3792,        random, radix_bits=4... mean=1.081e-04s (took 0.0s)
[ 7/20] Running N=    3792,        random, radix_bits=8... mean=8.805e-05s (took 0.0s)
[ 8/20] Running N=    6951,         zeros, radix_bits=1... mean=2.501e-04s (took 0.0s)
[ 8/20] Running N=    6951,         zeros, radix_bits=2... mean=1.603e-04s (took 0.0s)
[ 8/20] Running N=    6951,         zeros, radix_bits=4... mean=1.117e-04s (took 0.0s)
[ 8/20] Running N=    6951,         zeros, radix_bits=8... mean=1.104e-04s (took 0.0s)
[ 8/20] Running N=    6951, shuffled iota, radix_bits=1... mean=2.496e-04s (took 0.0s)
[ 8/20] Running N=    6951, shuffled iota, radix_bits=2... mean=1.621e-04s (took 0.0s)
[ 8/20] Running N=    6951, shuffled iota, radix_bits=4... mean=1.090e-04s (took 0.0s)
[ 8/20] Running N=    6951, shuffled iota, radix_bits=8... mean=8.683e-05s (took 0.0s)
[ 8/20] Running N=    6951,        random, radix_bits=1... mean=2.524e-04s (took 0.0s)
[ 8/20] Running N=    6951,        random, radix_bits=2... mean=1.577e-04s (took 0.0s)
[ 8/20] Running N=    6951,        random, radix_bits=4... mean=1.099e-04s (took 0.0s)
[ 8/20] Running N=    6951,        random, radix_bits=8... mean=1.020e-04s (took 0.0s)
[ 9/20] Running N=   12742,         zeros, radix_bits=1... mean=4.485e-04s (took 0.0s)
[ 9/20] Running N=   12742,         zeros, radix_bits=2... mean=2.646e-04s (took 0.0s)
[ 9/20] Running N=   12742,         zeros, radix_bits=4... mean=1.680e-04s (took 0.0s)
[ 9/20] Running N=   12742,         zeros, radix_bits=8... mean=1.623e-04s (took 0.0s)
[ 9/20] Running N=   12742, shuffled iota, radix_bits=1... mean=4.490e-04s (took 0.0s)
[ 9/20] Running N=   12742, shuffled iota, radix_bits=2... mean=2.653e-04s (took 0.0s)
[ 9/20] Running N=   12742, shuffled iota, radix_bits=4... mean=1.576e-04s (took 0.0s)
[ 9/20] Running N=   12742, shuffled iota, radix_bits=8... mean=1.170e-04s (took 0.0s)
[ 9/20] Running N=   12742,        random, radix_bits=1... mean=4.746e-04s (took 0.0s)
[ 9/20] Running N=   12742,        random, radix_bits=2... mean=2.616e-04s (took 0.0s)
[ 9/20] Running N=   12742,        random, radix_bits=4... mean=1.636e-04s (took 0.0s)
[ 9/20] Running N=   12742,        random, radix_bits=8... mean=1.311e-04s (took 0.0s)
[10/20] Running N=   23357,         zeros, radix_bits=1... mean=6.424e-04s (took 0.0s)
[10/20] Running N=   23357,         zeros, radix_bits=2... mean=3.710e-04s (took 0.0s)
[10/20] Running N=   23357,         zeros, radix_bits=4... mean=2.196e-04s (took 0.0s)
[10/20] Running N=   23357,         zeros, radix_bits=8... mean=2.166e-04s (took 0.0s)
[10/20] Running N=   23357, shuffled iota, radix_bits=1... mean=6.444e-04s (took 0.0s)
[10/20] Running N=   23357, shuffled iota, radix_bits=2... mean=3.727e-04s (took 0.0s)
[10/20] Running N=   23357, shuffled iota, radix_bits=4... mean=2.128e-04s (took 0.0s)
[10/20] Running N=   23357, shuffled iota, radix_bits=8... mean=1.461e-04s (took 0.0s)
[10/20] Running N=   23357,        random, radix_bits=1... mean=6.451e-04s (took 0.0s)
[10/20] Running N=   23357,        random, radix_bits=2... mean=3.617e-04s (took 0.0s)
[10/20] Running N=   23357,        random, radix_bits=4... mean=2.156e-04s (took 0.0s)
[10/20] Running N=   23357,        random, radix_bits=8... mean=1.786e-04s (took 0.0s)
[11/20] Running N=   42813,         zeros, radix_bits=1... mean=1.210e-03s (took 0.0s)
[11/20] Running N=   42813,         zeros, radix_bits=2... mean=6.637e-04s (took 0.0s)
[11/20] Running N=   42813,         zeros, radix_bits=4... mean=3.812e-04s (took 0.0s)
[11/20] Running N=   42813,         zeros, radix_bits=8... mean=3.777e-04s (took 0.0s)
[11/20] Running N=   42813, shuffled iota, radix_bits=1... mean=1.211e-03s (took 0.0s)
[11/20] Running N=   42813, shuffled iota, radix_bits=2... mean=6.628e-04s (took 0.0s)
[11/20] Running N=   42813, shuffled iota, radix_bits=4... mean=3.657e-04s (took 0.0s)
[11/20] Running N=   42813, shuffled iota, radix_bits=8... mean=2.374e-04s (took 0.0s)
[11/20] Running N=   42813,        random, radix_bits=1... mean=1.223e-03s (took 0.0s)
[11/20] Running N=   42813,        random, radix_bits=2... mean=6.658e-04s (took 0.0s)
[11/20] Running N=   42813,        random, radix_bits=4... mean=3.682e-04s (took 0.0s)
[11/20] Running N=   42813,        random, radix_bits=8... mean=2.513e-04s (took 0.0s)
[12/20] Running N=   78475,         zeros, radix_bits=1... mean=2.003e-03s (took 0.0s)
[12/20] Running N=   78475,         zeros, radix_bits=2... mean=1.148e-03s (took 0.0s)
[12/20] Running N=   78475,         zeros, radix_bits=4... mean=6.107e-04s (took 0.0s)
[12/20] Running N=   78475,         zeros, radix_bits=8... mean=5.841e-04s (took 0.0s)
[12/20] Running N=   78475, shuffled iota, radix_bits=1... mean=1.998e-03s (took 0.0s)
[12/20] Running N=   78475, shuffled iota, radix_bits=2... mean=1.069e-03s (took 0.0s)
[12/20] Running N=   78475, shuffled iota, radix_bits=4... mean=5.699e-04s (took 0.0s)
[12/20] Running N=   78475, shuffled iota, radix_bits=8... mean=3.537e-04s (took 0.0s)
[12/20] Running N=   78475,        random, radix_bits=1... mean=2.000e-03s (took 0.0s)
[12/20] Running N=   78475,        random, radix_bits=2... mean=1.095e-03s (took 0.0s)
[12/20] Running N=   78475,        random, radix_bits=4... mean=5.745e-04s (took 0.0s)
[12/20] Running N=   78475,        random, radix_bits=8... mean=3.940e-04s (took 0.0s)
[13/20] Running N=  143844,         zeros, radix_bits=1... mean=3.543e-03s (took 0.1s)
[13/20] Running N=  143844,         zeros, radix_bits=2... mean=1.902e-03s (took 0.0s)
[13/20] Running N=  143844,         zeros, radix_bits=4... mean=1.038e-03s (took 0.0s)
[13/20] Running N=  143844,         zeros, radix_bits=8... mean=1.010e-03s (took 0.0s)
[13/20] Running N=  143844, shuffled iota, radix_bits=1... mean=3.577e-03s (took 0.1s)
[13/20] Running N=  143844, shuffled iota, radix_bits=2... mean=1.877e-03s (took 0.0s)
[13/20] Running N=  143844, shuffled iota, radix_bits=4... mean=9.789e-04s (took 0.0s)
[13/20] Running N=  143844, shuffled iota, radix_bits=8... mean=5.896e-04s (took 0.0s)
[13/20] Running N=  143844,        random, radix_bits=1... mean=3.551e-03s (took 0.1s)
[13/20] Running N=  143844,        random, radix_bits=2... mean=1.873e-03s (took 0.0s)
[13/20] Running N=  143844,        random, radix_bits=4... mean=9.818e-04s (took 0.0s)
[13/20] Running N=  143844,        random, radix_bits=8... mean=6.393e-04s (took 0.0s)
[14/20] Running N=  263665,         zeros, radix_bits=1... mean=6.434e-03s (took 0.1s)
[14/20] Running N=  263665,         zeros, radix_bits=2... mean=3.407e-03s (took 0.1s)
[14/20] Running N=  263665,         zeros, radix_bits=4... mean=1.855e-03s (took 0.0s)
[14/20] Running N=  263665,         zeros, radix_bits=8... mean=1.795e-03s (took 0.0s)
[14/20] Running N=  263665, shuffled iota, radix_bits=1... mean=6.469e-03s (took 0.1s)
[14/20] Running N=  263665, shuffled iota, radix_bits=2... mean=3.378e-03s (took 0.1s)
[14/20] Running N=  263665, shuffled iota, radix_bits=4... mean=1.751e-03s (took 0.0s)
[14/20] Running N=  263665, shuffled iota, radix_bits=8... mean=1.008e-03s (took 0.0s)
[14/20] Running N=  263665,        random, radix_bits=1... mean=6.428e-03s (took 0.1s)
[14/20] Running N=  263665,        random, radix_bits=2... mean=3.386e-03s (took 0.1s)
[14/20] Running N=  263665,        random, radix_bits=4... mean=1.745e-03s (took 0.0s)
[14/20] Running N=  263665,        random, radix_bits=8... mean=1.094e-03s (took 0.0s)
[15/20] Running N=  483293,         zeros, radix_bits=1... mean=1.146e-02s (took 0.2s)
[15/20] Running N=  483293,         zeros, radix_bits=2... mean=6.033e-03s (took 0.1s)
[15/20] Running N=  483293,         zeros, radix_bits=4... mean=3.254e-03s (took 0.1s)
[15/20] Running N=  483293,         zeros, radix_bits=8... mean=3.167e-03s (took 0.1s)
[15/20] Running N=  483293, shuffled iota, radix_bits=1... mean=1.148e-02s (took 0.2s)
[15/20] Running N=  483293, shuffled iota, radix_bits=2... mean=5.997e-03s (took 0.1s)
[15/20] Running N=  483293, shuffled iota, radix_bits=4... mean=3.059e-03s (took 0.1s)
[15/20] Running N=  483293, shuffled iota, radix_bits=8... mean=1.733e-03s (took 0.0s)
[15/20] Running N=  483293,        random, radix_bits=1... mean=1.148e-02s (took 0.2s)
[15/20] Running N=  483293,        random, radix_bits=2... mean=6.006e-03s (took 0.1s)
[15/20] Running N=  483293,        random, radix_bits=4... mean=3.063e-03s (took 0.1s)
[15/20] Running N=  483293,        random, radix_bits=8... mean=1.886e-03s (took 0.0s)
[16/20] Running N=  885866,         zeros, radix_bits=1... mean=2.118e-02s (took 0.4s)
[16/20] Running N=  885866,         zeros, radix_bits=2... mean=1.112e-02s (took 0.2s)
[16/20] Running N=  885866,         zeros, radix_bits=4... mean=5.956e-03s (took 0.1s)
[16/20] Running N=  885866,         zeros, radix_bits=8... mean=5.774e-03s (took 0.1s)
[16/20] Running N=  885866, shuffled iota, radix_bits=1... mean=2.127e-02s (took 0.4s)
[16/20] Running N=  885866, shuffled iota, radix_bits=2... mean=1.105e-02s (took 0.2s)
[16/20] Running N=  885866, shuffled iota, radix_bits=4... mean=5.590e-03s (took 0.1s)
[16/20] Running N=  885866, shuffled iota, radix_bits=8... mean=3.103e-03s (took 0.1s)
[16/20] Running N=  885866,        random, radix_bits=1... mean=2.119e-02s (took 0.4s)
[16/20] Running N=  885866,        random, radix_bits=2... mean=1.104e-02s (took 0.2s)
[16/20] Running N=  885866,        random, radix_bits=4... mean=5.604e-03s (took 0.1s)
[16/20] Running N=  885866,        random, radix_bits=8... mean=3.367e-03s (took 0.1s)
[17/20] Running N= 1623776,         zeros, radix_bits=1... mean=3.856e-02s (took 0.8s)
[17/20] Running N= 1623776,         zeros, radix_bits=2... mean=2.022e-02s (took 0.4s)
[17/20] Running N= 1623776,         zeros, radix_bits=4... mean=1.082e-02s (took 0.2s)
[17/20] Running N= 1623776,         zeros, radix_bits=8... mean=1.057e-02s (took 0.2s)
[17/20] Running N= 1623776, shuffled iota, radix_bits=1... mean=3.863e-02s (took 0.8s)
[17/20] Running N= 1623776, shuffled iota, radix_bits=2... mean=2.015e-02s (took 0.4s)
[17/20] Running N= 1623776, shuffled iota, radix_bits=4... mean=1.023e-02s (took 0.2s)
[17/20] Running N= 1623776, shuffled iota, radix_bits=8... mean=5.727e-03s (took 0.1s)
[17/20] Running N= 1623776,        random, radix_bits=1... mean=3.858e-02s (took 0.8s)
[17/20] Running N= 1623776,        random, radix_bits=2... mean=2.023e-02s (took 0.4s)
[17/20] Running N= 1623776,        random, radix_bits=4... mean=1.019e-02s (took 0.2s)
[17/20] Running N= 1623776,        random, radix_bits=8... mean=6.051e-03s (took 0.1s)
[18/20] Running N= 2976351,         zeros, radix_bits=1... mean=9.600e-02s (took 1.9s)
[18/20] Running N= 2976351,         zeros, radix_bits=2... mean=5.054e-02s (took 1.0s)
[18/20] Running N= 2976351,         zeros, radix_bits=4... mean=2.692e-02s (took 0.5s)
[18/20] Running N= 2976351,         zeros, radix_bits=8... mean=2.689e-02s (took 0.5s)
[18/20] Running N= 2976351, shuffled iota, radix_bits=1... mean=9.697e-02s (took 1.9s)
[18/20] Running N= 2976351, shuffled iota, radix_bits=2... mean=5.108e-02s (took 1.0s)
[18/20] Running N= 2976351, shuffled iota, radix_bits=4... mean=2.579e-02s (took 0.5s)
[18/20] Running N= 2976351, shuffled iota, radix_bits=8... mean=1.483e-02s (took 0.3s)
[18/20] Running N= 2976351,        random, radix_bits=1... mean=9.596e-02s (took 1.9s)
[18/20] Running N= 2976351,        random, radix_bits=2... mean=5.084e-02s (took 1.0s)
[18/20] Running N= 2976351,        random, radix_bits=4... mean=2.572e-02s (took 0.5s)
[18/20] Running N= 2976351,        random, radix_bits=8... mean=1.547e-02s (took 0.3s)
[19/20] Running N= 5455594,         zeros, radix_bits=1... mean=1.485e-01s (took 3.0s)
[19/20] Running N= 5455594,         zeros, radix_bits=2... mean=7.924e-02s (took 1.6s)
[19/20] Running N= 5455594,         zeros, radix_bits=4... mean=4.284e-02s (took 0.9s)
[19/20] Running N= 5455594,         zeros, radix_bits=8... mean=4.057e-02s (took 0.8s)
[19/20] Running N= 5455594, shuffled iota, radix_bits=1... mean=1.514e-01s (took 3.0s)
[19/20] Running N= 5455594, shuffled iota, radix_bits=2... mean=8.107e-02s (took 1.6s)
[19/20] Running N= 5455594, shuffled iota, radix_bits=4... mean=4.303e-02s (took 0.9s)
[19/20] Running N= 5455594, shuffled iota, radix_bits=8... mean=2.180e-02s (took 0.4s)
[19/20] Running N= 5455594,        random, radix_bits=1... mean=1.514e-01s (took 3.0s)
[19/20] Running N= 5455594,        random, radix_bits=2... mean=8.112e-02s (took 1.6s)
[19/20] Running N= 5455594,        random, radix_bits=4... mean=4.297e-02s (took 0.9s)
[19/20] Running N= 5455594,        random, radix_bits=8... mean=2.259e-02s (took 0.5s)
[20/20] Running N=10000000,         zeros, radix_bits=1... mean=2.583e-01s (took 4.1s)
[20/20] Running N=10000000,         zeros, radix_bits=2... mean=1.399e-01s (took 2.8s)
[20/20] Running N=10000000,         zeros, radix_bits=4... mean=7.764e-02s (took 1.6s)
[20/20] Running N=10000000,         zeros, radix_bits=8... mean=7.201e-02s (took 1.4s)
[20/20] Running N=10000000, shuffled iota, radix_bits=1... mean=2.589e-01s (took 4.2s)
[20/20] Running N=10000000, shuffled iota, radix_bits=2... mean=1.389e-01s (took 2.8s)
[20/20] Running N=10000000, shuffled iota, radix_bits=4... mean=7.481e-02s (took 1.5s)
[20/20] Running N=10000000, shuffled iota, radix_bits=8... mean=4.133e-02s (took 0.8s)
[20/20] Running N=10000000,        random, radix_bits=1... mean=2.570e-01s (took 4.1s)
[20/20] Running N=10000000,        random, radix_bits=2... mean=1.414e-01s (took 2.8s)
[20/20] Running N=10000000,        random, radix_bits=4... mean=7.811e-02s (took 1.6s)
[20/20] Running N=10000000,        random, radix_bits=8... mean=4.287e-02s (took 0.9s)

Plot the digit histogram performance benchmarks, one figure per key distribution

151 color_cycle = plt.rcParams["axes.prop_cycle"].by_key()["color"]
152
153
154 def before_plot(ax_plot):
155     Nobj = np.array(particle_counts)
156     Time1G = Nobj / 1e9
157     ax_plot.plot(
158         particle_counts, Time1G, color="grey", linestyle="-", alpha=0.7, label="1G obj/sec"
159     )
160
161
162 for case in key_cases:
163     plot_data = {}
164     for i, radix_bits in enumerate(radix_bits_list):
165         plot_data[f"radix_bits={radix_bits}"] = {
166             "x": particle_counts,
167             "y": results[case][radix_bits],
168             "color": color_cycle[i % len(color_cycle)],
169             "label": f"radix_bits={radix_bits} (u32)",
170             "linestyle": "--",
171             "marker": ".",
172         }
173
174     make_std_bench_plot(
175         plot_data,
176         xlabel="Number of elements",
177         ylabel="Time (s)",
178         title=f"digit histogram performance benchmarks ({case} keys)",
179         end_label_fmt=lambda y: f"{y:.2e} s",
180         before_plot_func=before_plot,
181     )
182     plt.show()
  • digit histogram performance benchmarks (zeros keys)
  • digit histogram performance benchmarks (shuffled iota keys)
  • digit histogram performance benchmarks (random keys)

Plot the digit histogram performance benchmarks (bandwidth), one figure per key distribution. The keys are read only once whatever the number of digit places, the histogram itself being negligible in size.

189 for case in key_cases:
190     plot_data = {}
191     for i, radix_bits in enumerate(radix_bits_list):
192         Nobj = np.array(particle_counts)
193         Bytes = 4 * Nobj  # 1 u32 key read per element (sizeof = 4)
194         BW = Bytes / np.array(results[case][radix_bits])
195         plot_data[f"radix_bits={radix_bits}"] = {
196             "x": particle_counts,
197             "y": BW,
198             "color": color_cycle[i % len(color_cycle)],
199             "label": f"radix_bits={radix_bits} (u32)",
200             "linestyle": "--",
201             "marker": ".",
202         }
203
204     make_std_bench_plot(
205         plot_data,
206         xlabel="Number of elements",
207         ylabel="Bandwidth (B.s^-1)",
208         title=f"digit histogram performance benchmarks ({case} keys)",
209         end_label_fmt=lambda y: f"{y / 1e9:.2f} GB.s^-1",
210     )
211     plt.show()
  • digit histogram performance benchmarks (zeros keys)
  • digit histogram performance benchmarks (shuffled iota keys)
  • digit histogram performance benchmarks (random keys)

Plot the histograms of the 4 digit places of 8 bits for each key distribution

216 N_plot = 1000000
217
218 fig, axs = plt.subplots(1, len(key_cases), figsize=(15, 4), layout="constrained")
219 for ax, case in zip(axs, key_cases):
220     hist = compute_digit_histogram(make_keys(case, N_plot), 8)
221     for p in range(4):
222         ax.plot(hist[p * 256 : (p + 1) * 256], label=f"digit place {p} (bits {8 * p}-{8 * p + 7})")
223     ax.set_xlabel("digit value")
224     ax.set_ylabel("count")
225     ax.set_yscale("symlog")
226     ax.set_title(f"{case} keys")
227 axs[0].legend()
228 fig.suptitle(f"digit histogram (radix_bits=8, {N_plot} u32 keys)")
229 plt.show()
digit histogram (radix_bits=8, 1000000 u32 keys), zeros keys, shuffled iota keys, random keys

Total running time of the script: (1 minutes 16.335 seconds)

Estimated memory usage: 594 MB

Gallery generated by Sphinx-Gallery