gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
dueling.test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019, 2020 Inria
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <gtest/gtest.h>
30
31#include <cstddef>
32#include <cstdint>
33#include <memory>
34#include <tuple>
35#include <vector>
36
37#include "base/sat_counter.hh"
39
40using namespace gem5;
41
46TEST(DuelerTest, SetSample)
47{
48 const int num_sampled_ids = 3;
49 bool team;
50 Dueler dueler;
51
52 // Initially nobody is sampled
53 for (int id = 0; id < 64; id++) {
54 ASSERT_FALSE(dueler.isSample(1ULL << id, team));
55 }
56
57 // Mark the first num_sampled_ids as samples and assign alternating teams
58 team = false;
59 for (int id = 0; id < num_sampled_ids; id++) {
60 team = !team;
61 dueler.setSample(1ULL << id, team);
62 }
63
64 // Make sure that only the entries marked as samples previously are samples
65 bool expected_team = false;
66 for (int id = 0; id < 64; id++) {
67 expected_team = !expected_team;
68 const bool is_sample = dueler.isSample(1ULL << id, team);
69 if (id < num_sampled_ids) {
70 ASSERT_TRUE(is_sample);
71 ASSERT_EQ(team, expected_team);
72 } else {
73 ASSERT_FALSE(is_sample);
74 }
75 }
76
77}
78
79// We assume that the monitors are assigned sequential powers of
80// two ids starting from 1
81static uint64_t monitor_id = 0;
82
83class DuelingMonitorTest : public testing::TestWithParam<
84 std::tuple<unsigned, std::size_t, std::size_t, unsigned, double, double>>
85{
86 protected:
89
91 std::size_t constituencySize;
92
94 std::size_t teamSize;
95
97 unsigned numBits;
98
101
104
106 std::unique_ptr<DuelingMonitor> monitor;
107
108 void
109 SetUp() override
110 {
111 const unsigned num_entries = std::get<0>(GetParam());
112 constituencySize = std::get<1>(GetParam());
113 teamSize = std::get<2>(GetParam());
114 numBits = std::get<3>(GetParam());
115 lowThreshold = std::get<4>(GetParam());
116 highThreshold = std::get<5>(GetParam());
117
120
121 // Initialize entries
122 entries.resize(num_entries);
123 for (auto& entry : entries) {
124 monitor->initEntry(&entry);
125 }
126 }
127
128 void
129 TearDown() override
130 {
131 // Due to the way the DuelingMonitor works, this id is not testable
132 // anymore, so move to the next
133 monitor_id++;
134 }
135};
136
142{
143 const int expected_num_samples =
144 (entries.size() / constituencySize) * teamSize;
145
146 // Check whether the number of samples match expectation.
147 // Both teams must also have the same number of samples
148 int count_samples_true = 0;
149 int count_samples_false = 0;
150 bool team;
151 for (auto& entry : entries) {
152 if (entry.isSample(1ULL << monitor_id, team)) {
153 if (team) {
154 count_samples_true++;
155 } else {
156 count_samples_false++;
157 }
158 }
159 }
160 ASSERT_EQ(count_samples_true, count_samples_false);
161 ASSERT_EQ(count_samples_true, expected_num_samples);
162}
163
165TEST_P(DuelingMonitorTest, WinnerSelection)
166{
167 SatCounter32 expected_selector(numBits);
168 expected_selector.saturate();
169 expected_selector >>= 1;
170
171 // Initialize entries, and save a pointer to a sample of each
172 // team, and one no sample
173 int team_true_index = -1;
174 int team_false_index = -1;
175 int no_sample_index = -1;
176 for (int index = 0; index < entries.size(); index++) {
177 bool team;
178 if (entries[index].isSample(1ULL << monitor_id, team)) {
179 if (team) {
180 team_true_index = index;
181 } else {
182 team_false_index = index;
183 }
184 } else {
185 no_sample_index = index;
186 }
187 }
188 ASSERT_TRUE(team_true_index >= 0);
189 ASSERT_TRUE(team_false_index >= 0);
190
191 // Duel for team true only. If the monitor starts predicting false
192 // the threshold to use is the higher one. Otherwise, we should
193 // start expecting true to be the winner, and thus we use the
194 // low threshold
195 bool current_winner = monitor->getWinner();
196 double threshold = current_winner ? lowThreshold : highThreshold;
197 for (; expected_selector.calcSaturation() < 1.0;
198 expected_selector++) {
199 ASSERT_EQ(expected_selector.calcSaturation() >= threshold,
200 monitor->getWinner());
201 monitor->sample(&entries[team_true_index]);
202 }
203 current_winner = monitor->getWinner();
204 ASSERT_TRUE(current_winner);
205
206 // Duel for no sample. Should not change winner
207 if (no_sample_index >= 0) {
208 for (int i = 0; i < 200; i++) {
209 monitor->sample(&entries[no_sample_index]);
210 }
211 ASSERT_EQ(current_winner, monitor->getWinner());
212 }
213
214 // Duel for team false only. Now that we know that team true
215 // is winning, the low threshold must be passed in order to
216 // make team false win the duel
217 threshold = lowThreshold;
218 for (; expected_selector.calcSaturation() > 0.0;
219 expected_selector--) {
220 ASSERT_EQ(expected_selector.calcSaturation() >= threshold,
221 monitor->getWinner());
222 monitor->sample(&entries[team_false_index]);
223 }
224 current_winner = monitor->getWinner();
225 ASSERT_FALSE(current_winner);
226
227 // Duel for no sample. Should not change winner
228 if (no_sample_index >= 0) {
229 for (int i = 0; i < 200; i++) {
230 monitor->sample(&entries[no_sample_index]);
231 }
232 ASSERT_EQ(current_winner, monitor->getWinner());
233 }
234}
235
236// Test a few possible parameter combinations. There is a limitation on
237// the number of tests due to the maximum number of different ids. Because
238// of that, if a new test is added and it fails for no reason, make sure
239// that this limit has not been surpassed
241 ::testing::Values(
242 // Combinations of constituencies and teams
243 std::make_tuple(32, 2, 1, 1, 0.5, 0.5),
244 std::make_tuple(32, 4, 1, 1, 0.5, 0.5),
245 std::make_tuple(32, 4, 2, 1, 0.5, 0.5),
246 std::make_tuple(32, 8, 1, 1, 0.5, 0.5),
247 std::make_tuple(32, 8, 2, 1, 0.5, 0.5),
248 std::make_tuple(32, 8, 4, 1, 0.5, 0.5),
249 std::make_tuple(32, 16, 1, 1, 0.5, 0.5),
250 std::make_tuple(32, 16, 2, 1, 0.5, 0.5),
251 std::make_tuple(32, 16, 4, 1, 0.5, 0.5),
252 std::make_tuple(32, 16, 8, 1, 0.5, 0.5),
253
254 // Tests for the thresholds
255 std::make_tuple(16, 4, 1, 3, 0.5, 0.5),
256 std::make_tuple(16, 4, 1, 3, 0.1, 0.7),
257 std::make_tuple(16, 4, 1, 3, 0.4, 0.6),
258 std::make_tuple(16, 4, 1, 3, 0.8, 0.9),
259
260 // Test for larger tables
261 std::make_tuple(2048, 32, 4, 4, 0.4, 0.6))
262);
double highThreshold
The high threshold to change winner, acquired from params.
void SetUp() override
std::size_t constituencySize
The constituency size, acquired from params.
std::vector< Dueler > entries
A vector simulating a table-like structure.
std::unique_ptr< DuelingMonitor > monitor
The monitor instance being tested.
void TearDown() override
std::size_t teamSize
The size of a team, acquired from params.
double lowThreshold
The low threshold to change winner, acquired from params.
unsigned numBits
The number of bits in the selector, acquired from params.
A dueler is an entry that may or may not be accounted for sampling.
Definition dueling.hh:53
void setSample(uint64_t id, bool team)
Make this entry a sampling entry for a specific Dueling instance.
Definition dueling.cc:45
bool isSample(uint64_t id, bool &team) const
Check if entry is a sample for the given instance.
Definition dueling.cc:57
Duel between two sampled options to determine which is the winner.
Definition dueling.hh:108
STL vector class.
Definition stl.hh:37
static uint64_t monitor_id
INSTANTIATE_TEST_CASE_P(DuelingMonitorTests, DuelingMonitorTest, ::testing::Values(std::make_tuple(32, 2, 1, 1, 0.5, 0.5), std::make_tuple(32, 4, 1, 1, 0.5, 0.5), std::make_tuple(32, 4, 2, 1, 0.5, 0.5), std::make_tuple(32, 8, 1, 1, 0.5, 0.5), std::make_tuple(32, 8, 2, 1, 0.5, 0.5), std::make_tuple(32, 8, 4, 1, 0.5, 0.5), std::make_tuple(32, 16, 1, 1, 0.5, 0.5), std::make_tuple(32, 16, 2, 1, 0.5, 0.5), std::make_tuple(32, 16, 4, 1, 0.5, 0.5), std::make_tuple(32, 16, 8, 1, 0.5, 0.5), std::make_tuple(16, 4, 1, 3, 0.5, 0.5), std::make_tuple(16, 4, 1, 3, 0.1, 0.7), std::make_tuple(16, 4, 1, 3, 0.4, 0.6), std::make_tuple(16, 4, 1, 3, 0.8, 0.9), std::make_tuple(2048, 32, 4, 4, 0.4, 0.6)))
TEST_P(DuelingMonitorTest, CountSamples)
Test whether entry initialization creates exactly the amount of samples requested.
TEST(DuelerTest, SetSample)
Test whether dueler provides correct sampling functionality and assigns teams correctly.
GenericSatCounter< uint32_t > SatCounter32
double calcSaturation() const
Calculate saturation percentile of the current counter's value with regard to its maximum possible va...
T saturate()
Saturate the counter.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 30, 0 > index
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36

Generated on Mon May 26 2025 09:19:11 for gem5 by doxygen 1.13.2