C++ Library Extensions 2022.12.09
To help learn modern C++ programming
030-execution_policy.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
3#include <execution> // for Parallel Algorithm
4
6auto nl = tpf::nl;
8
9template<typename ElementType>
11{
12 public:
13 using element_type = ElementType;
14
15 private:
16 element_type m_x, m_y, m_z, m_color;
17
18 public:
21 m_x{x}, m_y{y}, m_z{z} { }
22
23 // vector cross product
24 friend vector_3d operator*(const vector_3d& L, const vector_3d& R)
25 {
26 // auto x = L.m_y * R.m_z - L.m_z * R.m_y;
27 // auto y = L.m_z * R.m_x - L.m_x * R.m_z;
28 // auto z = L.m_x * R.m_y - L.m_y * R.m_x;
29
30 return { L.m_y * R.m_z - L.m_z * R.m_y,
31 L.m_z * R.m_x - L.m_x * R.m_z,
32 L.m_x * R.m_y - L.m_y * R.m_x};
33 }
34
35 friend std::ostream& operator<<(std::ostream& os, const vector_3d& v)
36 {
37 os << "< " << v.m_x << ", " << v.m_y <<", " << v.m_z <<" >";
38 return os;
39 }
40};
41
42
44{
45 vector_3d<double> x{1, 0, 0}, y{0, 1, 0}, z{0, 0, 1};
46
47 auto v1 = y * z; // < 1, 0, 0 >
48 auto v2 = z * x; // < 0, 1, 0 >
49 auto v3 = x * y; // < 0, 0, 1 >
50
51 stream << "x = " << x<<", y = " << y <<", z = " << z << nl;
52 stream << "v1 = " << v1 <<", v2 = " << v2 <<", v3 = " << v3 << endl;
53}
54
55template<typename ExecutionPolicy>
56void naive_dangerous_parallel_algorithm(ExecutionPolicy policy, size_t test_count, size_t element_count)
57{
58 std::vector<vector_3d<float>> points; // 3 dimensional points
59 points.reserve(element_count);
60
61 // random number generator generating floats
62 // ranging from -10 to +10
63 auto generator = tpf::chrono_random::random_generator<float>(-10, +10);
64
65 vector_3d<float> rhs{generator(), generator(), generator()};
66
67 for(size_t i = 0; i < element_count; ++i)
68 // generate 3 floats and initialize vector_3d elements
69 points.emplace_back(generator(), generator(), generator());
70
71 // stream <<"Before Cross Product: \n" << points << nl;
72
74
75 for(size_t i = 0; i < test_count; ++i)
76 {
77 sw.reset();
78 std::transform(policy, points.begin(), points.end(),
79 points.begin(),
80 [&rhs](const auto& lhs){ return lhs * rhs; }
81 );
82
83 stream << "Elapsed - " << sw.elapsed_time() << nl;
84 }
85
86 // without endl, we cannot see anything
87 stream << endl;
88
89 // stream <<"\nAfter Cross Product: \n" << points << endl;
90}
91
93{
94 size_t element_count = 10'000'000;
95
96 stream <<"Sequential policy: \n";
97 naive_dangerous_parallel_algorithm(std::execution::seq, 5, element_count);
98
99 stream <<"\nParallel policy: \n";
100 naive_dangerous_parallel_algorithm(std::execution::par, 5, element_count);
101
102 stream <<"\nParallel Unsequenced policy: \n";
103 naive_dangerous_parallel_algorithm(std::execution::par_unseq, 5, element_count);
104}
105
107template<typename ExecutionPolicy>
108void why_naive_dangerous_parallel_algorithm(ExecutionPolicy policy, size_t test_count, size_t element_count)
109{
110 std::vector<vector_3d<float>> points; // 3 dimensional points
111 points.reserve(element_count);
112
113 // random number generator generating floats
114 // ranging from -10 to +10
115 auto generator = tpf::chrono_random::random_generator<float>(-10, +10);
116
117 vector_3d<float> rhs{generator(), generator(), generator()};
118
119 for(size_t i = 0; i < element_count; ++i)
120 // generate 3 floats and initialize vector_3d elements
121 points.emplace_back(generator(), generator(), generator());
122
123 // stream <<"Before Cross Product: \n" << points << nl;
124
126
127 for(size_t i = 0; i < test_count; ++i)
128 {
129 sw.reset();
130 std::transform(policy, points.begin(), points.end(),
131 points.begin(),
132
133 // When we use Parallel Algorithm,
134 // we should be extremely careful not to leak
135 // exceptions from the parallel callback functions.
136 [&rhs](const auto& lhs)
137 {
138 throw 1; // this cause system crash.
139
140 return lhs * rhs;
141 }
142 );
143
144 stream << "Elapsed - " << sw.elapsed_time() << nl;
145 }
146
147 // without endl, we cannot see anything
148 stream << endl;
149
150 // stream <<"\nAfter Cross Product: \n" << points << endl;
151}
152
154{
155 size_t element_count = 10'000'000;
156
157 try
158 {
159 stream <<"Sequential policy: \n";
160 why_naive_dangerous_parallel_algorithm(std::execution::seq, 5, element_count);
161
162 stream <<"You cannot see this message" << endl;
163 }
164 catch(...)
165 {
166 stream << "This does not work - you cannot see this message either" << endl;
167 }
168
169 // stream <<"\nParallel policy: \n";
170 // naive_dangerous_parallel_algorithm(std::execution::par, 5, element_count);
171
172 // stream <<"\nParallel Unsequenced policy: \n";
173 // naive_dangerous_parallel_algorithm(std::execution::par_unseq, 5, element_count);
174}
175
176int main()
177{
178 // test_vector_3d();
179 // test_naive_dangerous_parallel_algorithm();
181}
void why_naive_dangerous_parallel_algorithm(ExecutionPolicy policy, size_t test_count, size_t element_count)
void test_why_naive_dangerous_parallel_algorithm()
tpf::sstream stream
void naive_dangerous_parallel_algorithm(ExecutionPolicy policy, size_t test_count, size_t element_count)
void test_naive_dangerous_parallel_algorithm()
auto endl
auto nl
int main()
void test_vector_3d()
std::string elapsed_time(bool bReset=true, TimeUnit dummy_time=TimeUnit{}) const
ElementType element_type
friend std::ostream & operator<<(std::ostream &os, const vector_3d &v)
friend vector_3d operator*(const vector_3d &L, const vector_3d &R)
vector_3d(element_type x, element_type y, element_type z)
constexpr auto endl
Definition: tpf_output.hpp:973
constexpr auto nl
Definition: tpf_output.hpp:971
Stream output operators << are implemented.