-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
140 lines (119 loc) · 3.76 KB
/
main.cpp
File metadata and controls
140 lines (119 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// SPDX-License-Identifier: MIT
// Copyright (c) 2025 Daniil Shaposhnikov
#include <iostream>
#include <vector>
#include <random>
#include <thread>
#include <mutex>
#include <atomic>
#include <chrono>
#include <array>
// Task consts
#ifndef DIMENSIONS
#define DIMENSIONS 13
#endif
#ifndef AMOUNT
#define AMOUNT 50000
#endif
#ifndef RADIUS
#define RADIUS 1.0
#endif
#ifndef RADIUS_SQR
#define RADIUS_SQR (RADIUS * RADIUS)
#endif
#ifndef INNER_RADIUS
#define INNER_RADIUS (RADIUS - 0.1)
#endif
#ifndef INNER_RADIUS_SQR
#define INNER_RADIUS_SQR (INNER_RADIUS * INNER_RADIUS)
#endif
using Point = std::array<double, DIMENSIONS>;
bool insideSphere(const Point& p) {
double sum = 0.0;
for (double x : p) {
sum += x * x;
if (sum > RADIUS_SQR) return false;
}
return true;
}
bool insideInnerSphere(const Point& p) {
double sum = 0.0;
for (double x : p) {
sum += x * x;
if (sum > INNER_RADIUS_SQR) return false;
}
return true;
}
int main() {
unsigned int nThreads = std::thread::hardware_concurrency();
if (nThreads == 0) nThreads = 1;
std::cout << "Using threads: " << nThreads << "\n";
// Result vector and mutex
std::vector<Point> points;
points.reserve(AMOUNT);
std::mutex pointsMutex;
// Accepted points atomic
std::atomic<size_t> acceptedCount{0};
auto start_time = std::chrono::high_resolution_clock::now();
// Worker lambda
auto worker = [&](unsigned int threadIndex) {
std::mt19937_64 engine(std::random_device{}() + threadIndex);
std::uniform_real_distribution<double> dist(-RADIUS, RADIUS);
while (true) {
// Maybe already finished?
size_t curr = acceptedCount.load(std::memory_order_relaxed);
if (curr >= AMOUNT) break;
// Generating point
Point p;
for (double& x : p) {
x = dist(engine);
}
if (!insideSphere(p)) {
continue;
}
// Adding to acceptedCount
{
std::lock_guard<std::mutex> lg(pointsMutex);
if (acceptedCount.load(std::memory_order_relaxed) >= AMOUNT) {
break;
}
points.push_back(std::move(p));
acceptedCount.fetch_add(1, std::memory_order_relaxed);
}
}
};
std::vector<std::thread> threads;
threads.reserve(nThreads);
for (unsigned int i = 0; i < nThreads; ++i) {
threads.emplace_back(worker, i);
}
while (true) {
size_t done = acceptedCount.load(std::memory_order_relaxed);
if (done >= AMOUNT) break;
double pct = 100.0 * double(done) / double(AMOUNT);
std::cout << "\rProgress: " << int(pct) << "% (" << done << "/" << AMOUNT << ")" << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
std::cout << "\rProgress: 100% (" << AMOUNT << "/" << AMOUNT << ")" << std::endl;
// Ждём всех воркеров
for (auto& th : threads) {
if (th.joinable()) th.join();
}
size_t outsideCount = 0;
{
for (const auto& p : points) {
if (!insideInnerSphere(p)) {
++outsideCount;
}
}
}
auto end_time = std::chrono::high_resolution_clock::now();
double elapsed_ms = std::chrono::duration<double, std::milli>(end_time - start_time).count();
// Final output
std::cout << "Sphere dimensions: " << DIMENSIONS << "\n";
std::cout << "Points total: " << points.size() << "\n";
std::cout << "Points in outer sphere layer: " << outsideCount
<< " (~" << (100.0 * outsideCount / points.size()) << "%)\n";
std::cout << "Time elapsed: " << elapsed_ms << " ms\n";
return 0;
}