Skip to content

Commit 0649977

Browse files
committed
🎨 Generate lookup benchmark data
1 parent e1ba70e commit 0649977

File tree

3 files changed

+147
-86
lines changed

3 files changed

+147
-86
lines changed

benchmark/lookup/CMakeLists.txt

Lines changed: 80 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
11
add_versioned_package("gh:boost-ext/mph#v1.0.8")
22
add_versioned_package("gh:serge-sans-paille/frozen#292a811")
33

4-
# Define the variable values
5-
set(BENCH_ALG_NAMES
4+
function(gen_lookup_data)
5+
set(oneValueArgs TARGET TYPE SIZE OUTPUT)
6+
cmake_parse_arguments(GEN "" "${oneValueArgs}" "" ${ARGN})
7+
8+
set(script "${CMAKE_SOURCE_DIR}/tools/benchmark/gen_map_data.py")
9+
get_filename_component(DIR "${GEN_OUTPUT}" DIRECTORY)
10+
11+
add_custom_command(
12+
OUTPUT ${GEN_OUTPUT}
13+
COMMAND ${CMAKE_COMMAND} -E make_directory "${DIR}"
14+
COMMAND ${Python3_EXECUTABLE} ${script} --type ${GEN_TYPE} --size
15+
${GEN_SIZE} --output ${GEN_OUTPUT}
16+
DEPENDS ${script}
17+
COMMAND_EXPAND_LISTS)
18+
add_custom_target(${GEN_TARGET} DEPENDS ${GEN_OUTPUT})
19+
endfunction()
20+
21+
set(ALG_NAMES
622
std_map
723
std_unordered_map
824
frozen_map
@@ -15,54 +31,56 @@ set(BENCH_ALG_NAMES
1531
pseudo_pext_indirect_5
1632
pseudo_pext_indirect_6)
1733

18-
foreach(type IN ITEMS uint16 uint32)
19-
foreach(i RANGE 1 10)
20-
list(APPEND BENCH_DATASETS exp_${i}_${type})
21-
endforeach()
22-
foreach(i RANGE 20 100 10)
23-
list(APPEND BENCH_DATASETS exp_${i}_${type})
24-
endforeach()
25-
foreach(i RANGE 200 1000 100)
26-
list(APPEND BENCH_DATASETS exp_${i}_${type})
27-
endforeach()
28-
endforeach()
29-
3034
set(EXCLUDED_COMBINATIONS
31-
mph_pext_exp_70_uint32
32-
mph_pext_exp_80_uint32
33-
mph_pext_exp_90_uint32
34-
mph_pext_exp_100_uint32
35-
mph_pext_exp_200_uint32
36-
mph_pext_exp_300_uint32
37-
mph_pext_exp_400_uint32
38-
mph_pext_exp_500_uint32
39-
mph_pext_exp_600_uint32
40-
mph_pext_exp_700_uint32
41-
mph_pext_exp_800_uint32
42-
mph_pext_exp_900_uint32
43-
mph_pext_exp_1000_uint32
44-
mph_pext_exp_70_uint16
45-
mph_pext_exp_80_uint16
46-
mph_pext_exp_90_uint16
47-
mph_pext_exp_100_uint16
48-
mph_pext_exp_200_uint16
49-
mph_pext_exp_300_uint16
50-
mph_pext_exp_400_uint16
51-
mph_pext_exp_500_uint16
52-
mph_pext_exp_600_uint16
53-
mph_pext_exp_700_uint16
54-
mph_pext_exp_800_uint16
55-
mph_pext_exp_900_uint16
56-
mph_pext_exp_1000_uint16)
35+
mph_pext_exp_uint32_70
36+
mph_pext_exp_uint32_80
37+
mph_pext_exp_uint32_90
38+
mph_pext_exp_uint32_100
39+
mph_pext_exp_uint32_200
40+
mph_pext_exp_uint32_300
41+
mph_pext_exp_uint32_400
42+
mph_pext_exp_uint32_500
43+
mph_pext_exp_uint32_600
44+
mph_pext_exp_uint32_700
45+
mph_pext_exp_uint32_800
46+
mph_pext_exp_uint32_900
47+
mph_pext_exp_uint32_1000
48+
mph_pext_exp_uint16_70
49+
mph_pext_exp_uint16_80
50+
mph_pext_exp_uint16_90
51+
mph_pext_exp_uint16_100
52+
mph_pext_exp_uint16_200
53+
mph_pext_exp_uint16_300
54+
mph_pext_exp_uint16_400
55+
mph_pext_exp_uint16_500
56+
mph_pext_exp_uint16_600
57+
mph_pext_exp_uint16_700
58+
mph_pext_exp_uint16_800
59+
mph_pext_exp_uint16_900
60+
mph_pext_exp_uint16_1000)
5761

58-
# Generate all possible combinations of the variables
59-
foreach(BENCH_ALG_NAME ${BENCH_ALG_NAMES})
60-
foreach(BENCH_DATASET ${BENCH_DATASETS})
61-
if("${BENCH_ALG_NAME}_${BENCH_DATASET}" IN_LIST EXCLUDED_COMBINATIONS)
62+
function(gen_pp_benchmarks)
63+
set(oneValueArgs TYPE SIZE)
64+
cmake_parse_arguments(BM "" "${oneValueArgs}" "" ${ARGN})
65+
66+
set(DATASET exp_${BM_TYPE}_${BM_SIZE})
67+
set(HEADER "${CMAKE_BINARY_DIR}/benchmark/generated/${DATASET}.hpp")
68+
gen_lookup_data(
69+
TARGET
70+
bm_lookup_data_${DATASET}
71+
TYPE
72+
${BM_TYPE}
73+
SIZE
74+
${BM_SIZE}
75+
OUTPUT
76+
${HEADER})
77+
78+
foreach(ALG_NAME ${ALG_NAMES})
79+
if("${ALG_NAME}_${DATASET}" IN_LIST EXCLUDED_COMBINATIONS)
6280
continue()
6381
endif()
64-
set(name "${BENCH_ALG_NAME}_${BENCH_DATASET}_bench")
6582

83+
set(name "${ALG_NAME}_${DATASET}_bench")
6684
add_benchmark(
6785
${name}
6886
NANO
@@ -72,10 +90,23 @@ foreach(BENCH_ALG_NAME ${BENCH_ALG_NAMES})
7290
cib_lookup
7391
mph
7492
frozen-headers)
75-
target_compile_options(${name} PRIVATE -fconstexpr-steps=4000000000)
93+
target_compile_options(${name} PRIVATE -fconstexpr-steps=4000000000
94+
--include=${HEADER})
7695
target_compile_definitions(
77-
${name}
78-
PRIVATE ALG_NAME=bench_${BENCH_ALG_NAME}
79-
BENCH_DATASET=${BENCH_DATASET} ANKERL_NANOBENCH_IMPLEMENT)
96+
${name} PRIVATE ALG_NAME=bench_${ALG_NAME} DATASET=${DATASET}
97+
ANKERL_NANOBENCH_IMPLEMENT)
98+
add_dependencies(${name} bm_lookup_data_${DATASET})
99+
endforeach()
100+
endfunction()
101+
102+
foreach(type IN ITEMS uint16 uint32)
103+
foreach(i RANGE 1 10)
104+
gen_pp_benchmarks(TYPE ${type} SIZE ${i})
105+
endforeach()
106+
foreach(i RANGE 20 100 10)
107+
gen_pp_benchmarks(TYPE ${type} SIZE ${i})
108+
endforeach()
109+
foreach(i RANGE 200 1000 100)
110+
gen_pp_benchmarks(TYPE ${type} SIZE ${i})
80111
endforeach()
81112
endforeach()

benchmark/lookup/pseudo_pext.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44
#include "algorithms/frozen_unordered_map.hpp"
55
#include "algorithms/std_map.hpp"
66
#include "algorithms/std_unordered_map.hpp"
7-
#include "lookup_datasets.hpp"
87

98
#include <cstdio>
109

1110
#define STRINGIFY(S) #S
1211
#define STR(S) STRINGIFY(S)
1312

1413
int main() {
15-
printf("\n\n\ndataset: %s\n", STR(BENCH_DATASET));
14+
printf("\n\n\ndataset: %s\n", STR(DATASET));
1615
printf("algorithm: %s\n", STR(ALG_NAME));
17-
ALG_NAME<BENCH_DATASET, decltype(BENCH_DATASET[0].first)>(
18-
STR(BENCH_DATASET));
16+
ALG_NAME<DATASET, decltype(DATASET[0].first)>(STR(DATASET));
1917
}

tools/benchmark/gen_map_data.py

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,80 @@
1+
import argparse
12
import random
23

3-
print("""
4-
#pragma once
5-
6-
#include <array>
7-
#include <cstdint>
8-
#include <utility>
9-
""")
104

11-
def gen_table(name, size, t, f):
5+
def gen_table(size, t, fn, f):
6+
# ensure there are 'size' unique entries
127
keys = set()
13-
14-
# ensure there are 'size' entries and no duplicates
158
while len(keys) < size:
16-
keys.add(f())
17-
9+
keys.add(fn())
10+
1811
# build a mapping of keys to values such that the entire set
19-
# can be visted by repeatedly looking up the result
12+
# can be visited by repeatedly looking up the result
2013
keys = list(keys)
2114
values = keys[1:] + keys[:1]
2215

23-
print(f"constexpr auto {name} = std::array<std::pair<{t}, {t}>, {size}>{{{{")
24-
for k, v in zip(keys, values):
25-
print(f" {{0x{k:08x}u, 0x{v:08x}u}},")
26-
print("}};")
16+
indent = " " * 4
17+
f.write(
18+
f"constexpr auto exp_{t}_{size} = std::array<std::pair<std::{t}_t, std::{t}_t>, {size}>{{{{\n{indent}"
19+
)
20+
f.write(
21+
f",\n{indent}".join(
22+
f"{{0x{k:08x}u, 0x{v:08x}u}}" for k, v, in zip(keys, values)
23+
)
24+
)
25+
f.write("\n}};\n")
26+
27+
28+
def parse_cmdline():
29+
parser = argparse.ArgumentParser()
30+
parser.add_argument(
31+
"--type",
32+
type=str,
33+
choices=["uint32", "uint16"],
34+
required=True,
35+
help=("Unsigned integral type of the input data."),
36+
)
37+
parser.add_argument(
38+
"--size",
39+
type=int,
40+
required=True,
41+
help=("Number of items in the input data (e.g. 500)."),
42+
)
43+
parser.add_argument(
44+
"--output",
45+
type=str,
46+
required=True,
47+
help="Output filename for generated C++ code.",
48+
)
49+
return parser.parse_args()
2750

28-
def gen_exp_uint32_table(scale):
29-
for x in range(1, 10):
30-
count = x * scale
31-
gen_table(f"exp_{count}_uint32", count, "uint32_t", lambda: int(random.expovariate(10) * (1 << 28)))
3251

33-
gen_exp_uint32_table(1)
34-
gen_exp_uint32_table(10)
35-
gen_exp_uint32_table(100)
36-
gen_exp_uint32_table(1000)
52+
gen_fns = {
53+
"uint16": lambda: int(random.expovariate(10) * (1 << 14)) & 0xFFFF,
54+
"uint32": lambda: int(random.expovariate(10) * (1 << 28)),
55+
}
3756

3857

39-
def gen_exp_uint16_table(scale):
40-
for x in range(1, 10):
41-
count = x * scale
42-
gen_table(f"exp_{count}_uint16", count, "uint16_t", lambda: int(random.expovariate(10) * (1 << 14)) & 0xffff)
58+
def main():
59+
args = parse_cmdline()
60+
61+
with open(args.output, "w") as f:
62+
f.write(
63+
"""#pragma once
64+
65+
#include <array>
66+
#include <cstdint>
67+
#include <utility>
68+
69+
"""
70+
)
71+
gen_table(
72+
args.size,
73+
args.type,
74+
gen_fns[args.type],
75+
f,
76+
)
4377

4478

45-
gen_exp_uint16_table(1)
46-
gen_exp_uint16_table(10)
47-
gen_exp_uint16_table(100)
48-
gen_exp_uint16_table(1000)
79+
if __name__ == "__main__":
80+
main()

0 commit comments

Comments
 (0)