annotate libc/utils/benchmarks/LibcMemoryBenchmark.h @ 204:e348f3e5c8b2

ReadFromString worked.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 05 Jun 2021 15:35:13 +0900
parents 0572611fdcc8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1 //===-- Benchmark memory specific tools -------------------------*- C++ -*-===//
150
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 // This file complements the `benchmark` header with memory specific tools and
anatofuz
parents:
diff changeset
10 // benchmarking facilities.
anatofuz
parents:
diff changeset
11
anatofuz
parents:
diff changeset
12 #ifndef LLVM_LIBC_UTILS_BENCHMARK_MEMORY_BENCHMARK_H
anatofuz
parents:
diff changeset
13 #define LLVM_LIBC_UTILS_BENCHMARK_MEMORY_BENCHMARK_H
anatofuz
parents:
diff changeset
14
anatofuz
parents:
diff changeset
15 #include "LibcBenchmark.h"
anatofuz
parents:
diff changeset
16 #include "llvm/ADT/DenseMap.h"
anatofuz
parents:
diff changeset
17 #include "llvm/ADT/SmallVector.h"
anatofuz
parents:
diff changeset
18 #include "llvm/Support/Alignment.h"
anatofuz
parents:
diff changeset
19 #include <cstdint>
anatofuz
parents:
diff changeset
20 #include <random>
anatofuz
parents:
diff changeset
21
anatofuz
parents:
diff changeset
22 namespace llvm {
anatofuz
parents:
diff changeset
23 namespace libc_benchmarks {
anatofuz
parents:
diff changeset
24
anatofuz
parents:
diff changeset
25 //--------------
anatofuz
parents:
diff changeset
26 // Configuration
anatofuz
parents:
diff changeset
27 //--------------
anatofuz
parents:
diff changeset
28
anatofuz
parents:
diff changeset
29 // Specifies a range of sizes to explore.
anatofuz
parents:
diff changeset
30 struct SizeRange {
anatofuz
parents:
diff changeset
31 uint32_t From = 0; // Inclusive
anatofuz
parents:
diff changeset
32 uint32_t To = 1024; // Inclusive
anatofuz
parents:
diff changeset
33 uint32_t Step = 1;
anatofuz
parents:
diff changeset
34 };
anatofuz
parents:
diff changeset
35
anatofuz
parents:
diff changeset
36 // An object to define how to test a memory function.
anatofuz
parents:
diff changeset
37 struct StudyConfiguration {
anatofuz
parents:
diff changeset
38 // The number of run for the study.
anatofuz
parents:
diff changeset
39 uint32_t Runs = 1;
anatofuz
parents:
diff changeset
40
anatofuz
parents:
diff changeset
41 // The size of the buffers (1 buffer for memset but 2 for memcpy or memcmp).
anatofuz
parents:
diff changeset
42 // When testing small sizes, it's important to keep the total allocated
anatofuz
parents:
diff changeset
43 // size under the size of the L1 cache (usually 16 or 32KiB). The framework
anatofuz
parents:
diff changeset
44 // will also use 2KiB of additional L1 memory to store the function
anatofuz
parents:
diff changeset
45 // parameters.
anatofuz
parents:
diff changeset
46 uint32_t BufferSize = 8192;
anatofuz
parents:
diff changeset
47
anatofuz
parents:
diff changeset
48 // The range of sizes to exercise.
anatofuz
parents:
diff changeset
49 SizeRange Size;
anatofuz
parents:
diff changeset
50
anatofuz
parents:
diff changeset
51 MaybeAlign AddressAlignment; // Unset : Use start of buffer which is at
anatofuz
parents:
diff changeset
52 // least cache line aligned)
anatofuz
parents:
diff changeset
53 // 1 : Use random address,
anatofuz
parents:
diff changeset
54 // >1 : Use random address aligned to value.
anatofuz
parents:
diff changeset
55
anatofuz
parents:
diff changeset
56 // The value to use for memset.
anatofuz
parents:
diff changeset
57 uint8_t MemsetValue = 0;
anatofuz
parents:
diff changeset
58
anatofuz
parents:
diff changeset
59 // The mismatch position for memcmp.
anatofuz
parents:
diff changeset
60 uint32_t MemcmpMismatchAt = 0; // 0 : Buffer compare equal,
anatofuz
parents:
diff changeset
61 // >0 : Buffer compare different at byte N-1.
anatofuz
parents:
diff changeset
62 };
anatofuz
parents:
diff changeset
63
anatofuz
parents:
diff changeset
64 //--------
anatofuz
parents:
diff changeset
65 // Results
anatofuz
parents:
diff changeset
66 //--------
anatofuz
parents:
diff changeset
67
anatofuz
parents:
diff changeset
68 // The time to run one iteration of the function under test for the specified
anatofuz
parents:
diff changeset
69 // Size.
anatofuz
parents:
diff changeset
70 struct Measurement {
anatofuz
parents:
diff changeset
71 uint32_t Size = 0;
anatofuz
parents:
diff changeset
72 Duration Runtime = {};
anatofuz
parents:
diff changeset
73 };
anatofuz
parents:
diff changeset
74
anatofuz
parents:
diff changeset
75 // The measurements for a specific function.
anatofuz
parents:
diff changeset
76 struct FunctionMeasurements {
anatofuz
parents:
diff changeset
77 std::string Name;
anatofuz
parents:
diff changeset
78 std::vector<Measurement> Measurements;
anatofuz
parents:
diff changeset
79 };
anatofuz
parents:
diff changeset
80
anatofuz
parents:
diff changeset
81 // The root object containing all the data (configuration and measurements).
anatofuz
parents:
diff changeset
82 struct Study {
anatofuz
parents:
diff changeset
83 HostState Host;
anatofuz
parents:
diff changeset
84 BenchmarkOptions Options;
anatofuz
parents:
diff changeset
85 StudyConfiguration Configuration;
anatofuz
parents:
diff changeset
86 SmallVector<FunctionMeasurements, 4> Functions;
anatofuz
parents:
diff changeset
87 };
anatofuz
parents:
diff changeset
88
anatofuz
parents:
diff changeset
89 // Provides an aligned, dynamically allocated buffer.
anatofuz
parents:
diff changeset
90 class AlignedBuffer {
anatofuz
parents:
diff changeset
91 char *const Buffer = nullptr;
anatofuz
parents:
diff changeset
92 size_t Size = 0;
anatofuz
parents:
diff changeset
93
anatofuz
parents:
diff changeset
94 public:
anatofuz
parents:
diff changeset
95 static constexpr size_t Alignment = 1024;
anatofuz
parents:
diff changeset
96
anatofuz
parents:
diff changeset
97 explicit AlignedBuffer(size_t Size)
anatofuz
parents:
diff changeset
98 : Buffer(static_cast<char *>(aligned_alloc(1024, Size))), Size(Size) {}
anatofuz
parents:
diff changeset
99 ~AlignedBuffer() { free(Buffer); }
anatofuz
parents:
diff changeset
100
anatofuz
parents:
diff changeset
101 inline char *operator+(size_t Index) { return Buffer + Index; }
anatofuz
parents:
diff changeset
102 inline const char *operator+(size_t Index) const { return Buffer + Index; }
anatofuz
parents:
diff changeset
103 inline char &operator[](size_t Index) { return Buffer[Index]; }
anatofuz
parents:
diff changeset
104 inline const char &operator[](size_t Index) const { return Buffer[Index]; }
anatofuz
parents:
diff changeset
105 inline char *begin() { return Buffer; }
anatofuz
parents:
diff changeset
106 inline char *end() { return Buffer + Size; }
anatofuz
parents:
diff changeset
107 };
anatofuz
parents:
diff changeset
108
anatofuz
parents:
diff changeset
109 // Implements the ParameterProvider abstraction needed by the `benchmark`
anatofuz
parents:
diff changeset
110 // function. This implementation makes sure that all parameters will fit into
anatofuz
parents:
diff changeset
111 // `StorageSize` bytes. The total memory accessed during benchmark should be
anatofuz
parents:
diff changeset
112 // less than the data L1 cache, that is the storage for the ParameterProvider
anatofuz
parents:
diff changeset
113 // and the memory buffers.
anatofuz
parents:
diff changeset
114 template <typename Context, size_t StorageSize = 8 * 1024>
anatofuz
parents:
diff changeset
115 class SmallParameterProvider {
anatofuz
parents:
diff changeset
116 using ParameterType = typename Context::ParameterType;
anatofuz
parents:
diff changeset
117 ByteConstrainedArray<ParameterType, StorageSize> Parameters;
anatofuz
parents:
diff changeset
118 size_t LastIterations;
anatofuz
parents:
diff changeset
119 Context &Ctx;
anatofuz
parents:
diff changeset
120
anatofuz
parents:
diff changeset
121 public:
anatofuz
parents:
diff changeset
122 explicit SmallParameterProvider(Context &C) : Ctx(C) {}
anatofuz
parents:
diff changeset
123 SmallParameterProvider(const SmallParameterProvider &) = delete;
anatofuz
parents:
diff changeset
124 SmallParameterProvider &operator=(const SmallParameterProvider &) = delete;
anatofuz
parents:
diff changeset
125
anatofuz
parents:
diff changeset
126 // Useful to compute the histogram of the size parameter.
anatofuz
parents:
diff changeset
127 CircularArrayRef<ParameterType> getLastBatch() const {
anatofuz
parents:
diff changeset
128 return cycle(Parameters, LastIterations);
anatofuz
parents:
diff changeset
129 }
anatofuz
parents:
diff changeset
130
anatofuz
parents:
diff changeset
131 // Implements the interface needed by the `benchmark` function.
anatofuz
parents:
diff changeset
132 CircularArrayRef<ParameterType> generateBatch(size_t Iterations) {
anatofuz
parents:
diff changeset
133 LastIterations = Iterations;
anatofuz
parents:
diff changeset
134 Ctx.Randomize(Parameters);
anatofuz
parents:
diff changeset
135 return getLastBatch();
anatofuz
parents:
diff changeset
136 }
anatofuz
parents:
diff changeset
137 };
anatofuz
parents:
diff changeset
138
anatofuz
parents:
diff changeset
139 // Helper to generate random buffer offsets that satisfy the configuration
anatofuz
parents:
diff changeset
140 // constraints.
anatofuz
parents:
diff changeset
141 class OffsetDistribution {
anatofuz
parents:
diff changeset
142 std::uniform_int_distribution<uint32_t> Distribution;
anatofuz
parents:
diff changeset
143 uint32_t Factor;
anatofuz
parents:
diff changeset
144
anatofuz
parents:
diff changeset
145 public:
anatofuz
parents:
diff changeset
146 explicit OffsetDistribution(const StudyConfiguration &Conf);
anatofuz
parents:
diff changeset
147
anatofuz
parents:
diff changeset
148 template <class Generator> uint32_t operator()(Generator &G) {
anatofuz
parents:
diff changeset
149 return Distribution(G) * Factor;
anatofuz
parents:
diff changeset
150 }
anatofuz
parents:
diff changeset
151 };
anatofuz
parents:
diff changeset
152
anatofuz
parents:
diff changeset
153 // Helper to generate random buffer offsets that satisfy the configuration
anatofuz
parents:
diff changeset
154 // constraints. It is specifically designed to benchmark `memcmp` functions
anatofuz
parents:
diff changeset
155 // where we may want the Nth byte to differ.
anatofuz
parents:
diff changeset
156 class MismatchOffsetDistribution {
anatofuz
parents:
diff changeset
157 std::uniform_int_distribution<size_t> MismatchIndexSelector;
anatofuz
parents:
diff changeset
158 llvm::SmallVector<uint32_t, 16> MismatchIndices;
anatofuz
parents:
diff changeset
159 const uint32_t MismatchAt;
anatofuz
parents:
diff changeset
160
anatofuz
parents:
diff changeset
161 public:
anatofuz
parents:
diff changeset
162 explicit MismatchOffsetDistribution(const StudyConfiguration &Conf);
anatofuz
parents:
diff changeset
163
anatofuz
parents:
diff changeset
164 explicit operator bool() const { return !MismatchIndices.empty(); }
anatofuz
parents:
diff changeset
165
anatofuz
parents:
diff changeset
166 const llvm::SmallVectorImpl<uint32_t> &getMismatchIndices() const {
anatofuz
parents:
diff changeset
167 return MismatchIndices;
anatofuz
parents:
diff changeset
168 }
anatofuz
parents:
diff changeset
169
anatofuz
parents:
diff changeset
170 template <class Generator> uint32_t operator()(Generator &G, uint32_t Size) {
anatofuz
parents:
diff changeset
171 const uint32_t MismatchIndex = MismatchIndices[MismatchIndexSelector(G)];
anatofuz
parents:
diff changeset
172 // We need to position the offset so that a mismatch occurs at MismatchAt.
anatofuz
parents:
diff changeset
173 if (Size >= MismatchAt)
anatofuz
parents:
diff changeset
174 return MismatchIndex - MismatchAt;
anatofuz
parents:
diff changeset
175 // Size is too small to trigger the mismatch.
anatofuz
parents:
diff changeset
176 return MismatchIndex - Size - 1;
anatofuz
parents:
diff changeset
177 }
anatofuz
parents:
diff changeset
178 };
anatofuz
parents:
diff changeset
179
anatofuz
parents:
diff changeset
180 } // namespace libc_benchmarks
anatofuz
parents:
diff changeset
181 } // namespace llvm
anatofuz
parents:
diff changeset
182
anatofuz
parents:
diff changeset
183 #endif // LLVM_LIBC_UTILS_BENCHMARK_MEMORY_BENCHMARK_H