Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
thread.test.cpp
Go to the documentation of this file.
1#include "thread.hpp"
3#include <atomic>
4#include <gtest/gtest.h>
5#include <set>
6#include <thread>
7
8namespace bb {
9
10class ThreadTest : public ::testing::Test {
11 protected:
12 void SetUp() override
13 {
14 // Store original concurrency for restoration
16 }
17
18 void TearDown() override
19 {
20 // Restore original concurrency
22 }
23
25};
26
27// Test basic parallel_for functionality
28TEST_F(ThreadTest, BasicParallelFor)
29{
30 constexpr size_t num_iterations = 100;
31 std::vector<char> flags(num_iterations, 0);
32
33 parallel_for(num_iterations, [&](size_t i) { flags[i] = 1; });
34
35 // All iterations should have been executed
36 for (size_t i = 0; i < num_iterations; ++i) {
37 EXPECT_TRUE(flags[i]);
38 }
39}
40
41// Test thread count calculation
42TEST_F(ThreadTest, CalculateNumThreads)
43{
45
46 // With default min iterations per thread (16)
47 // 160 iterations / 16 = 10 desired threads, min(10, 8) = 8
48 EXPECT_EQ(calculate_num_threads(160), 8);
49
50 // 64 iterations / 16 = 4 desired threads, min(4, 8) = 4
51 EXPECT_EQ(calculate_num_threads(64), 4);
52
53 // 8 iterations / 16 = 0 desired threads, but should be at least 1
54 EXPECT_EQ(calculate_num_threads(8), 1);
55
56 // Custom min iterations per thread
57 // 100 iterations / 10 = 10 desired threads, min(10, 8) = 8
58 EXPECT_EQ(calculate_num_threads(100, 10), 8);
59
60 // 30 iterations / 10 = 3 desired threads, min(3, 8) = 3
61 EXPECT_EQ(calculate_num_threads(30, 10), 3);
62}
63
64// Test thread count calculation with power of 2
65TEST_F(ThreadTest, CalculateNumThreadsPow2)
66{
68
69 // With default min iterations per thread (16)
70 // 160 iterations / 16 = 10 desired, nearest power of 2 is 8, min(8, 8) = 8
71 EXPECT_EQ(calculate_num_threads_pow2(160), 8);
72
73 // 64 iterations / 16 = 4 desired, power of 2 is 4, min(4, 8) = 4
74 EXPECT_EQ(calculate_num_threads_pow2(64), 4);
75
76 // 96 iterations / 16 = 6 desired, nearest power of 2 is 4, min(4, 8) = 4
77 EXPECT_EQ(calculate_num_threads_pow2(96), 4);
78
79 // 8 iterations / 16 = 0 desired, should be at least 1
80 EXPECT_EQ(calculate_num_threads_pow2(8), 1);
81}
82
83// Test parallel_for with zero iterations
84TEST_F(ThreadTest, ZeroIterations)
85{
86 size_t counter = 0;
87
88 parallel_for(0, [&](size_t) { counter++; });
89
90 EXPECT_EQ(counter, 0);
91}
92
93// Test parallel_for with one iteration
94TEST_F(ThreadTest, OneIteration)
95{
96 size_t counter = 0;
97
98 parallel_for(1, [&](size_t i) {
99 counter++;
100 EXPECT_EQ(i, 0);
101 });
102
103 EXPECT_EQ(counter, 1);
104}
105
106// Test parallel_for_range
107TEST_F(ThreadTest, ParallelForRange)
108{
109 constexpr size_t num_points = 100;
110 std::vector<char> flags(num_points, 0);
111
112 parallel_for_range(num_points, [&](size_t start, size_t end) {
113 for (size_t i = start; i < end; ++i) {
114 flags[i] = 1;
115 }
116 });
117
118 // All iterations should have been executed
119 for (size_t i = 0; i < num_points; ++i) {
120 EXPECT_TRUE(flags[i]);
121 }
122}
123
124// Test parallel_for_range with threshold
125TEST_F(ThreadTest, ParallelForRangeThreshold)
126{
127 constexpr size_t num_points = 10;
128 std::vector<char> flags(num_points, 0);
129
130 std::atomic<size_t> call_count{ 0 };
131
132 // Set threshold to 10, so with exactly 10 points it should run sequentially (1 call)
134 num_points,
135 [&](size_t start, size_t end) {
136 call_count++;
137 for (size_t i = start; i < end; ++i) {
138 flags[i] = 1;
139 }
140 },
141 10);
142
143 // All iterations should have been executed
144 for (size_t i = 0; i < num_points; ++i) {
145 EXPECT_TRUE(flags[i]);
146 }
147
148 // Should have been called exactly once (sequential)
149 EXPECT_EQ(call_count, 1);
150}
151
152// Test get_num_cpus with different hardware concurrency values
153TEST_F(ThreadTest, HardwareConcurrency)
154{
156 EXPECT_EQ(get_num_cpus(), 1);
157
159 EXPECT_EQ(get_num_cpus(), 4);
160
162 EXPECT_EQ(get_num_cpus(), 16);
163
165 EXPECT_EQ(get_num_cpus(), 128);
166}
167
168// Test get_num_cpus_pow2
169TEST_F(ThreadTest, HardwareConcurrencyPow2)
170{
172 EXPECT_EQ(get_num_cpus_pow2(), 1);
173
175 EXPECT_EQ(get_num_cpus_pow2(), 4);
176
178 EXPECT_EQ(get_num_cpus_pow2(), 4); // Round down to power of 2
179
181 EXPECT_EQ(get_num_cpus_pow2(), 4); // Round down to power of 2
182
184 EXPECT_EQ(get_num_cpus_pow2(), 8);
185
187 EXPECT_EQ(get_num_cpus_pow2(), 8); // Round down to power of 2
188
190 EXPECT_EQ(get_num_cpus_pow2(), 16);
191}
192
193// Test that spawned threads can use parallel_for with set_parallel_for_concurrency
194TEST_F(ThreadTest, SpawnedThreadsCanUseParallelFor)
195{
197
198 constexpr size_t num_outer = 2;
199 constexpr size_t num_inner = 100;
200 std::vector<std::vector<char>> results(num_outer, std::vector<char>(num_inner, 0));
201
202 auto worker = [&](size_t outer_idx) {
204 parallel_for(num_inner, [&](size_t inner_idx) { results[outer_idx][inner_idx] = 1; });
205 };
206
207 std::vector<std::thread> threads;
208 for (size_t i = 0; i < num_outer; ++i) {
209 threads.emplace_back(worker, i);
210 }
211 for (auto& t : threads) {
212 t.join();
213 }
214
215 // Verify all work completed
216 for (size_t i = 0; i < num_outer; ++i) {
217 for (size_t j = 0; j < num_inner; ++j) {
218 EXPECT_TRUE(results[i][j]);
219 }
220 }
221}
222} // namespace bb
void TearDown() override
void SetUp() override
size_t original_concurrency
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
size_t get_num_cpus_pow2()
Definition thread.hpp:25
size_t get_num_cpus()
Definition thread.cpp:33
size_t calculate_num_threads(size_t num_iterations, size_t min_iterations_per_thread)
calculates number of threads to create based on minimum iterations per thread
Definition thread.cpp:238
size_t calculate_num_threads_pow2(size_t num_iterations, size_t min_iterations_per_thread)
calculates number of threads to create based on minimum iterations per thread, guaranteed power of 2
Definition thread.cpp:254
void set_parallel_for_concurrency(size_t num_cores)
Definition thread.cpp:23
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:111
void parallel_for_range(size_t num_points, const std::function< void(size_t, size_t)> &func, size_t no_multhreading_if_less_or_equal)
Split a loop into several loops running in parallel.
Definition thread.cpp:141
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13