Skip to content

Commit b6d8261

Browse files
committed
Add week 6 projects
1 parent 000317f commit b6d8261

File tree

10 files changed

+1014
-0
lines changed

10 files changed

+1014
-0
lines changed

Calculate/Calculate.cpp

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
#include <algorithm>
2+
#include <atomic>
3+
#include <chrono>
4+
#include <future>
5+
#include <iostream>
6+
#include <mutex>
7+
#include <numeric>
8+
#include <random>
9+
#include <ranges>
10+
#include <thread>
11+
#include <vector>
12+
13+
// Sequential
14+
int in_seq{0}, total_seq{0};
15+
// Atomic
16+
std::atomic<int> in_atomic_1{0}, total_atomic_1{0};
17+
std::atomic<int> in_atomic_2{0}, total_atomic_2{0};
18+
// Mutex
19+
int in_mutex_1{0}, total_mutex_1{0};
20+
int in_mutex_2{0}, total_mutex_2{0};
21+
std::mutex mtx;
22+
23+
struct vector2f
24+
{
25+
float x, y;
26+
};
27+
28+
vector2f get_random_point()
29+
{
30+
thread_local std::random_device rd;
31+
thread_local std::default_random_engine eng(rd());
32+
thread_local std::uniform_real_distribution<float> distr(-1, 1);
33+
return {distr(eng), distr(eng)};
34+
}
35+
36+
void count_points_atomic_1(int number_of_points);
37+
void count_points_atomic_2(int start, int end);
38+
39+
void count_points_mutex_1(int number_of_points);
40+
void count_points_mutex_2(int start, int end);
41+
42+
int count_points_future_1(int num_of_points);
43+
int count_points_future_2(int start, int end);
44+
45+
void count_points(int number)
46+
{
47+
total_seq += number;
48+
for (int i{}; i < number; ++i)
49+
{
50+
const auto point{get_random_point()};
51+
if (point.x * point.x + point.y * point.y < 1.f)
52+
{
53+
++in_seq;
54+
}
55+
}
56+
}
57+
58+
void count_points_atomic_1(int number_of_points)
59+
{
60+
int in = 0;
61+
for (int i = 0; i < number_of_points; ++i)
62+
{
63+
const auto point = get_random_point();
64+
if (point.x * point.x + point.y * point.y < 1.f)
65+
{
66+
++in;
67+
}
68+
}
69+
in_atomic_1 += in;
70+
total_atomic_1 += number_of_points;
71+
}
72+
73+
void count_points_atomic_2(int start, int end)
74+
{
75+
int in = 0;
76+
for (int i = start; i < end; ++i)
77+
{
78+
const auto point = get_random_point();
79+
if (point.x * point.x + point.y * point.y < 1.f)
80+
{
81+
++in;
82+
}
83+
}
84+
in_atomic_2 += in;
85+
total_atomic_2 += end - start;
86+
}
87+
88+
void count_points_mutex_1(int number_of_points)
89+
{
90+
int in = 0;
91+
for (int i = 0; i < number_of_points; ++i)
92+
{
93+
const auto point = get_random_point();
94+
if (point.x * point.x + point.y * point.y < 1.f)
95+
{
96+
++in;
97+
}
98+
}
99+
std::lock_guard lock(mtx);
100+
in_mutex_1 += in;
101+
total_mutex_1 += number_of_points;
102+
}
103+
104+
void count_points_mutex_2(int start, int end)
105+
{
106+
int in = 0;
107+
for (int i = start; i < end; ++i)
108+
{
109+
const auto point = get_random_point();
110+
if (point.x * point.x + point.y * point.y < 1.f)
111+
{
112+
++in;
113+
}
114+
}
115+
std::lock_guard lock(mtx);
116+
in_mutex_2 += in;
117+
total_mutex_2 += end - start;
118+
}
119+
120+
int count_points_future_1(int num_of_points)
121+
{
122+
int in = 0;
123+
for (int i = 0; i < num_of_points; ++i)
124+
{
125+
const auto point = get_random_point();
126+
if (point.x * point.x + point.y * point.y < 1.f)
127+
{
128+
++in;
129+
}
130+
}
131+
return in;
132+
}
133+
134+
int count_points_future_2(int start, int end)
135+
{
136+
int in = 0;
137+
for (int i = start; i < end; ++i)
138+
{
139+
const auto point = get_random_point();
140+
if (point.x * point.x + point.y * point.y < 1.f)
141+
{
142+
++in;
143+
}
144+
}
145+
return in;
146+
}
147+
148+
int main()
149+
{
150+
std::vector<long long> measured_times;
151+
152+
// const int numThreads = std::thread::hardware_concurrency();
153+
constexpr int num_threads = 10;
154+
constexpr int total_points = 100'000'000;
155+
constexpr int points_per_thread = total_points / num_threads;
156+
157+
//--------------------------------------------------------------------------------
158+
// Sequential
159+
//--------------------------------------------------------------------------------
160+
for (int i = 0; i < 10; ++i)
161+
{
162+
auto start_time = std::chrono::high_resolution_clock::now();
163+
count_points(total_points);
164+
auto end_time = std::chrono::high_resolution_clock::now();
165+
measured_times.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
166+
}
167+
auto [min1, max1] = std::ranges::minmax_element(measured_times);
168+
auto average = (std::accumulate(measured_times.begin(), measured_times.end(), 0LL) - (*min1 + *max1)) / (measured_times.size() - 2);
169+
std::cout << "Average time (sequence): " << average << "ms\n";
170+
std::cout << "Pi accuracy: " << 1.f * in_seq / total_seq * 4 << "\n";
171+
std::cout << "In: " << in_seq << " Total: " << total_seq << "\n\n";
172+
173+
measured_times.clear();
174+
175+
//--------------------------------------------------------------------------------
176+
// Atomic
177+
//--------------------------------------------------------------------------------
178+
for (int i = 0; i < 10; ++i)
179+
{
180+
auto start_time = std::chrono::high_resolution_clock::now();
181+
{
182+
std::vector<std::jthread> threads(10);
183+
for (int j = 0; j < num_threads; ++j)
184+
{
185+
threads.emplace_back(count_points_atomic_1, points_per_thread);
186+
}
187+
}
188+
auto end_time = std::chrono::high_resolution_clock::now();
189+
measured_times.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
190+
}
191+
auto [min2, max2] = std::ranges::minmax_element(measured_times);
192+
average = (std::accumulate(measured_times.begin(), measured_times.end(), 0LL) - (*min2 + *max2)) / (measured_times.size() - 2);
193+
std::cout << "Average time (atomic) - number_of_points: " << average << "ms\n";
194+
std::cout << "Pi accuracy: " << 1.f * in_atomic_1 / total_atomic_1 * 4 << "\n";
195+
std::cout << "In: " << in_atomic_1 << " Total: " << total_atomic_1 << "\n\n";
196+
197+
measured_times.clear();
198+
199+
for (int i = 0; i < 10; ++i)
200+
{
201+
auto start_time = std::chrono::high_resolution_clock::now();
202+
{
203+
std::vector<std::jthread> threads(10);
204+
for (int j = 0; j < num_threads; ++j)
205+
{
206+
int start = j * points_per_thread;
207+
int end = (j == num_threads - 1) ? total_points : (j + 1) * points_per_thread;
208+
threads.emplace_back(count_points_atomic_2, start, end);
209+
}
210+
}
211+
auto end_time = std::chrono::high_resolution_clock::now();
212+
measured_times.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
213+
}
214+
auto [min3, max3] = std::ranges::minmax_element(measured_times);
215+
average = (std::accumulate(measured_times.begin(), measured_times.end(), 0LL) - (*min3 + *max3)) / (measured_times.size() - 2);
216+
std::cout << "Average time (atomic) - start, end: " << average << "ms\n";
217+
std::cout << "Pi accuracy: " << 1.f * in_atomic_2 / total_atomic_2 * 4 << "\n";
218+
std::cout << "In: " << in_atomic_2 << " Total: " << total_atomic_2 << "\n\n";
219+
220+
measured_times.clear();
221+
222+
//--------------------------------------------------------------------------------
223+
// Mutex
224+
//--------------------------------------------------------------------------------
225+
for (int i = 0; i < 10; ++i)
226+
{
227+
auto start_time = std::chrono::high_resolution_clock::now();
228+
{
229+
std::vector<std::jthread> threads(10);
230+
for (int j = 0; j < num_threads; ++j)
231+
{
232+
threads.emplace_back(count_points_mutex_1, points_per_thread);
233+
}
234+
}
235+
auto end_time = std::chrono::high_resolution_clock::now();
236+
measured_times.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
237+
}
238+
auto [min4, max4] = std::ranges::minmax_element(measured_times);
239+
average = (std::accumulate(measured_times.begin(), measured_times.end(), 0LL) - (*min4 + *max4)) / (measured_times.size() - 2);
240+
std::cout << "Average time (mutex) - number_of_points: " << average << "ms\n";
241+
std::cout << "Pi accuracy: " << 1.f * in_mutex_1 / total_mutex_1 * 4 << "\n";
242+
std::cout << "In: " << in_mutex_1 << " Total: " << total_mutex_1 << "\n\n";
243+
244+
measured_times.clear();
245+
246+
for (int i = 0; i < 10; ++i)
247+
{
248+
auto start_time = std::chrono::high_resolution_clock::now();
249+
{
250+
std::vector<std::jthread> threads(10);
251+
for (int j = 0; j < num_threads; ++j)
252+
{
253+
int start = j * points_per_thread;
254+
int end = (j == num_threads - 1) ? total_points : (j + 1) * points_per_thread;
255+
threads.emplace_back(count_points_mutex_2, start, end);
256+
}
257+
}
258+
auto end_time = std::chrono::high_resolution_clock::now();
259+
measured_times.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
260+
}
261+
auto [min5, max5] = std::ranges::minmax_element(measured_times);
262+
average = (std::accumulate(measured_times.begin(), measured_times.end(), 0LL) - (*min5 + *max5)) / (measured_times.size() - 2);
263+
std::cout << "Average time (mutex) - start, end: " << average << "ms\n";
264+
std::cout << "Pi accuracy: " << 1.f * in_mutex_2 / total_mutex_2 * 4 << "\n";
265+
std::cout << "In: " << in_mutex_2 << " Total: " << total_mutex_2 << "\n\n";
266+
267+
measured_times.clear();
268+
269+
//--------------------------------------------------------------------------------
270+
// Future
271+
//--------------------------------------------------------------------------------
272+
std::vector<float> pi_values;
273+
int totalInCircle = 0;
274+
for (int i = 0; i < 10; ++i)
275+
{
276+
auto start_time = std::chrono::high_resolution_clock::now();
277+
{
278+
std::vector<std::future<int>> futures;
279+
for (int j = 0; j < num_threads; ++j)
280+
{
281+
futures.push_back(std::async(std::launch::async, count_points_future_1, points_per_thread));
282+
}
283+
for (auto &future : futures)
284+
{
285+
totalInCircle += future.get();
286+
}
287+
pi_values.push_back(1.f * totalInCircle / total_points * 4);
288+
if (i != 9)
289+
totalInCircle = 0;
290+
}
291+
auto end_time = std::chrono::high_resolution_clock::now();
292+
measured_times.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
293+
}
294+
auto [min6, max6] = std::ranges::minmax_element(measured_times);
295+
average = (std::accumulate(measured_times.begin(), measured_times.end(), 0LL) - (*min6 + *max6)) / (measured_times.size() - 2);
296+
std::cout << "Average time (future) - int: " << average << "ms\n";
297+
std::cout << "Pi accuracy: " << 1.f * std::accumulate(pi_values.begin(), pi_values.end(), 0.f) / pi_values.size() << "\n";
298+
std::cout << "In: " << totalInCircle << " Total: " << total_points << "\n\n";
299+
300+
measured_times.clear();
301+
pi_values.clear();
302+
totalInCircle = 0;
303+
304+
for (int i = 0; i < 10; ++i)
305+
{
306+
auto start_time = std::chrono::high_resolution_clock::now();
307+
{
308+
std::vector<std::future<int>> futures;
309+
for (int j = 0; j < num_threads; ++j)
310+
{
311+
int start = j * points_per_thread;
312+
int end = (j == num_threads - 1) ? total_points : (j + 1) * points_per_thread;
313+
futures.push_back(std::async(std::launch::async, count_points_future_2, start, end));
314+
}
315+
for (auto &future : futures)
316+
{
317+
totalInCircle += future.get();
318+
}
319+
pi_values.push_back(1.f * totalInCircle / total_points * 4);
320+
if (i != 9)
321+
totalInCircle = 0;
322+
}
323+
auto end_time = std::chrono::high_resolution_clock::now();
324+
measured_times.push_back(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
325+
}
326+
auto [min7, max7] = std::ranges::minmax_element(measured_times);
327+
average = (std::accumulate(measured_times.begin(), measured_times.end(), 0LL) - (*min7 + *max7)) / (measured_times.size() - 2);
328+
std::cout << "Average time (future) - start, end: " << average << "ms\n";
329+
std::cout << "Pi accuracy: " << 1.f * std::accumulate(pi_values.begin(), pi_values.end(), 0.f) / pi_values.size() << "\n";
330+
std::cout << "In: " << totalInCircle << " Total: " << total_points << "\n";
331+
}

Calculate/Calculate.sln

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.9.34701.34
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Calculate", "Calculate.vcxproj", "{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|x64 = Debug|x64
11+
Debug|x86 = Debug|x86
12+
Release|x64 = Release|x64
13+
Release|x86 = Release|x86
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Debug|x64.ActiveCfg = Debug|x64
17+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Debug|x64.Build.0 = Debug|x64
18+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Debug|x86.ActiveCfg = Debug|Win32
19+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Debug|x86.Build.0 = Debug|Win32
20+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Release|x64.ActiveCfg = Release|x64
21+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Release|x64.Build.0 = Release|x64
22+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Release|x86.ActiveCfg = Release|Win32
23+
{9D3C750A-7CA6-4DC1-8FC7-AEC4F0C371A5}.Release|x86.Build.0 = Release|Win32
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {807CCEF8-46C5-41F3-93A3-1B4857CBA7FB}
30+
EndGlobalSection
31+
EndGlobal

0 commit comments

Comments
 (0)