Skip to content

Commit 4a204cc

Browse files
CopilotWenyinWei
andcommitted
Add comprehensive parallelism integration demo with real ODE solvers
Co-authored-by: WenyinWei <[email protected]>
1 parent 50df9af commit 4a204cc

File tree

4 files changed

+291
-6
lines changed

4 files changed

+291
-6
lines changed

include/diffeq.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,10 @@
3737
#include <interfaces/integration_interface.hpp> // Unified interface for all domains
3838

3939
// Enhanced parallelism capabilities with modern C++ features
40-
#include <execution/parallelism_facade.hpp> // Unified parallelism interface (Facade pattern)
41-
#include <execution/parallelism_facade_impl.hpp> // Implementation details
42-
#include <execution/parallel_builder.hpp> // Fluent interface for configuration (Builder pattern)
43-
#include <execution/modern_executor.hpp> // Modern C++ executor support with coroutines
44-
#include <execution/hardware_support.hpp> // Hardware-specific execution (CUDA, OpenCL, FPGA, MPI)
40+
#include <execution/parallelism_facade_clean.hpp> // Unified parallelism interface (Facade pattern)
41+
#include <execution/parallel_builder.hpp> // Fluent interface for configuration (Builder pattern)
42+
#include <execution/modern_executor.hpp> // Modern C++ executor support with coroutines
43+
#include <execution/hardware_support.hpp> // Hardware-specific execution (CUDA, OpenCL, FPGA, MPI)
4544

4645
/**
4746
* @file diffeq.hpp

include/execution/modern_executor.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#pragma once
22

3-
#include <execution/parallelism_facade.hpp>
3+
#include <execution/parallelism_facade_clean.hpp>
44
#include <future>
55
#include <coroutine>
66
#include <exception>
77
#include <type_traits>
8+
#include <utility>
9+
#include <variant>
810

911
namespace diffeq::execution {
1012

parallelism_integration_demo

143 KB
Binary file not shown.

parallelism_integration_demo.cpp

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
#include <execution/parallelism_facade_clean.hpp>
2+
#include <execution/parallel_builder.hpp>
3+
#include <integrators/ode/rk4.hpp>
4+
#include <integrators/ode/euler.hpp>
5+
#include <integrators/ode/rk45.hpp>
6+
#include <iostream>
7+
#include <vector>
8+
#include <chrono>
9+
#include <random>
10+
#include <cmath>
11+
12+
/**
13+
* @brief Integration Example with Enhanced Parallelism
14+
*
15+
* This example demonstrates how the new parallelism capabilities
16+
* integrate seamlessly with existing diffeq integrators.
17+
*/
18+
19+
int main() {
20+
std::cout << "=== Enhanced Parallelism Integration with ODE Solvers ===\n\n";
21+
22+
// Example 1: Parallel integration of multiple initial conditions
23+
std::cout << "1. Parallel Integration of Multiple Initial Conditions\n";
24+
std::cout << " Solving harmonic oscillator: d²x/dt² = -ω²x with different initial conditions\n\n";
25+
26+
// Define the harmonic oscillator system
27+
auto harmonic_oscillator = [](double /*t*/, const std::vector<double>& state, std::vector<double>& derivative) {
28+
const double omega = 1.0; // Natural frequency
29+
derivative[0] = state[1]; // dx/dt = v
30+
derivative[1] = -omega * omega * state[0]; // dv/dt = -ω²x
31+
};
32+
33+
// Create multiple initial conditions
34+
std::vector<std::vector<double>> initial_conditions = {
35+
{1.0, 0.0}, // x=1, v=0
36+
{0.0, 1.0}, // x=0, v=1
37+
{0.5, 0.5}, // x=0.5, v=0.5
38+
{-1.0, 0.0}, // x=-1, v=0
39+
{0.0, -1.0}, // x=0, v=-1
40+
{2.0, 0.0}, // x=2, v=0
41+
{0.0, 2.0}, // x=0, v=2
42+
{1.5, -0.5} // x=1.5, v=-0.5
43+
};
44+
45+
// Configure parallelism for optimal performance
46+
auto parallel_facade = diffeq::execution::parallel_execution()
47+
.target_cpu()
48+
.use_thread_pool()
49+
.workers(std::thread::hardware_concurrency())
50+
.normal_priority()
51+
.enable_load_balancing()
52+
.build();
53+
54+
std::cout << "Using " << parallel_facade->get_max_concurrency() << " worker threads\n";
55+
56+
const double dt = 0.01;
57+
const double end_time = 2.0 * M_PI; // One full period
58+
59+
auto start_time = std::chrono::high_resolution_clock::now();
60+
61+
// Parallel integration using the facade
62+
parallel_facade->parallel_for_each(initial_conditions.begin(), initial_conditions.end(),
63+
[&](std::vector<double>& state) {
64+
// Create integrator for this thread (RK4 for accuracy)
65+
auto integrator = diffeq::integrators::ode::RK4Integrator<std::vector<double>, double>(harmonic_oscillator);
66+
67+
double t = 0.0;
68+
while (t < end_time) {
69+
double step_size = std::min(dt, end_time - t);
70+
integrator.step(state, step_size);
71+
t += step_size;
72+
}
73+
});
74+
75+
auto end_time_chrono = std::chrono::high_resolution_clock::now();
76+
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time_chrono - start_time);
77+
78+
std::cout << "Integration completed in " << duration.count() << "ms\n";
79+
std::cout << "Final states (should be close to initial due to periodicity):\n";
80+
for (size_t i = 0; i < initial_conditions.size(); ++i) {
81+
const auto& state = initial_conditions[i];
82+
std::cout << " Condition " << i+1 << ": x=" << state[0] << ", v=" << state[1] << "\n";
83+
}
84+
85+
// Example 2: Monte Carlo simulation with stochastic differential equations
86+
std::cout << "\n2. Monte Carlo SDE Simulation with GPU-Style Parallelism\n";
87+
std::cout << " Simulating geometric Brownian motion for financial modeling\n\n";
88+
89+
// Configure for high-throughput Monte Carlo
90+
auto monte_carlo_facade = diffeq::execution::presets::monte_carlo().build();
91+
92+
const size_t num_simulations = 1000; // Reduced for demo
93+
const double S0 = 100.0; // Initial stock price
94+
const double mu = 0.05; // Drift
95+
const double sigma = 0.2; // Volatility
96+
const double T = 1.0; // Time horizon
97+
98+
std::cout << "Running " << num_simulations << " Monte Carlo simulations...\n";
99+
100+
// Create storage for results
101+
std::vector<double> final_prices(num_simulations);
102+
std::vector<std::future<double>> simulation_futures;
103+
104+
start_time = std::chrono::high_resolution_clock::now();
105+
106+
// Launch parallel simulations
107+
for (size_t i = 0; i < num_simulations; ++i) {
108+
simulation_futures.push_back(monte_carlo_facade->async([=]() {
109+
// Each simulation uses its own random number generator
110+
std::mt19937 rng(std::random_device{}() + i);
111+
std::normal_distribution<double> normal(0.0, 1.0);
112+
113+
// Simple Geometric Brownian Motion system
114+
auto gbm_system = [mu](double /*t*/, const std::vector<double>& state, std::vector<double>& derivative) {
115+
derivative[0] = mu * state[0]; // Drift term
116+
};
117+
118+
auto integrator = diffeq::integrators::ode::EulerIntegrator<std::vector<double>, double>(gbm_system);
119+
120+
std::vector<double> state = {S0};
121+
double t = 0.0;
122+
const double dt_sim = 0.01;
123+
124+
while (t < T) {
125+
// Deterministic step
126+
integrator.step(state, dt_sim);
127+
128+
// Add stochastic component (simplified Euler-Maruyama)
129+
double dW = normal(rng) * std::sqrt(dt_sim);
130+
state[0] += sigma * state[0] * dW;
131+
132+
t += dt_sim;
133+
}
134+
135+
return state[0]; // Return final price
136+
}));
137+
}
138+
139+
// Collect results
140+
for (size_t i = 0; i < num_simulations; ++i) {
141+
final_prices[i] = simulation_futures[i].get();
142+
}
143+
144+
end_time_chrono = std::chrono::high_resolution_clock::now();
145+
duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time_chrono - start_time);
146+
147+
// Calculate statistics
148+
double mean_price = 0.0;
149+
double min_price = final_prices[0];
150+
double max_price = final_prices[0];
151+
152+
for (double price : final_prices) {
153+
mean_price += price;
154+
min_price = std::min(min_price, price);
155+
max_price = std::max(max_price, price);
156+
}
157+
mean_price /= num_simulations;
158+
159+
double variance = 0.0;
160+
for (double price : final_prices) {
161+
variance += (price - mean_price) * (price - mean_price);
162+
}
163+
variance /= (num_simulations - 1);
164+
165+
std::cout << "Monte Carlo Results:\n";
166+
std::cout << " Simulation time: " << duration.count() << "ms\n";
167+
std::cout << " Throughput: " << (num_simulations * 1000.0) / duration.count() << " simulations/second\n";
168+
std::cout << " Mean final price: $" << mean_price << "\n";
169+
std::cout << " Price range: $" << min_price << " - $" << max_price << "\n";
170+
std::cout << " Standard deviation: $" << std::sqrt(variance) << "\n";
171+
std::cout << " Expected price (theoretical): $" << S0 * std::exp(mu * T) << "\n";
172+
173+
// Example 3: Real-time integration for control systems
174+
std::cout << "\n3. Real-time Integration for Control Systems\n";
175+
std::cout << " Simulating a controlled pendulum with real-time constraints\n\n";
176+
177+
// Configure for real-time execution
178+
auto realtime_facade = diffeq::execution::presets::real_time_systems().build();
179+
180+
// Controlled pendulum system
181+
auto controlled_pendulum = [](double t, const std::vector<double>& state, std::vector<double>& derivative) {
182+
const double g = 9.81; // Gravity
183+
const double L = 1.0; // Pendulum length
184+
const double b = 0.1; // Damping
185+
186+
double theta = state[0]; // Angle
187+
double theta_dot = state[1]; // Angular velocity
188+
189+
// Simple PD controller
190+
double u = -10.0 * theta - 2.0 * theta_dot; // Control torque
191+
192+
derivative[0] = theta_dot;
193+
derivative[1] = -(g/L) * std::sin(theta) - b * theta_dot + u;
194+
};
195+
196+
std::vector<double> pendulum_state = {0.5, 0.0}; // Initial angle 0.5 rad, no initial velocity
197+
const double control_dt = 0.001; // 1ms control loop (1kHz)
198+
const double control_time = 1.0; // 1 second of control (reduced for demo)
199+
200+
std::cout << "Running real-time control loop at 1kHz for " << control_time << " seconds...\n";
201+
202+
start_time = std::chrono::high_resolution_clock::now();
203+
auto integrator = diffeq::integrators::ode::RK4Integrator<std::vector<double>, double>(controlled_pendulum);
204+
205+
size_t steps = 0;
206+
for (double t = 0.0; t < control_time; t += control_dt) {
207+
// Execute one control step with real-time priority
208+
auto control_future = realtime_facade->async([&]() {
209+
integrator.step(pendulum_state, control_dt);
210+
});
211+
212+
control_future.wait();
213+
steps++;
214+
215+
// Log every 200ms
216+
if (steps % 200 == 0) {
217+
std::cout << " t=" << t << "s, angle=" << pendulum_state[0]
218+
<< " rad, velocity=" << pendulum_state[1] << " rad/s\n";
219+
}
220+
}
221+
222+
end_time_chrono = std::chrono::high_resolution_clock::now();
223+
duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time_chrono - start_time);
224+
225+
std::cout << "Control loop completed in " << duration.count() << "ms\n";
226+
std::cout << "Average loop time: " << (duration.count() * 1000.0) / steps << " microseconds\n";
227+
std::cout << "Final pendulum state: angle=" << pendulum_state[0]
228+
<< " rad, velocity=" << pendulum_state[1] << " rad/s\n";
229+
230+
// Example 4: Parallel pattern usage
231+
std::cout << "\n4. Parallel Pattern Demonstration\n";
232+
std::cout << " Using parallel_map and parallel_reduce with ODE solutions\n\n";
233+
234+
// Create a range of parameters for parametric study
235+
std::vector<double> damping_values = {0.01, 0.05, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0};
236+
237+
// Parallel map: solve ODE for each damping value
238+
auto final_energies = diffeq::execution::patterns::parallel_map(
239+
damping_values.begin(), damping_values.end(),
240+
[](double damping) {
241+
// Damped harmonic oscillator
242+
auto damped_oscillator = [damping](double /*t*/, const std::vector<double>& state, std::vector<double>& derivative) {
243+
derivative[0] = state[1]; // dx/dt = v
244+
derivative[1] = -state[0] - 2.0 * damping * state[1]; // dv/dt = -x - 2γv
245+
};
246+
247+
auto integrator = diffeq::integrators::ode::RK45Integrator<std::vector<double>, double>(damped_oscillator);
248+
249+
std::vector<double> state = {1.0, 0.0}; // Initial: x=1, v=0
250+
double t = 0.0;
251+
const double dt = 0.01;
252+
const double end_time = 10.0;
253+
254+
while (t < end_time) {
255+
integrator.step(state, dt);
256+
t += dt;
257+
}
258+
259+
// Calculate final energy: E = 0.5 * (x² + v²)
260+
return 0.5 * (state[0] * state[0] + state[1] * state[1]);
261+
}
262+
);
263+
264+
std::cout << "Parallel parametric study results:\n";
265+
for (size_t i = 0; i < damping_values.size(); ++i) {
266+
std::cout << " Damping γ=" << damping_values[i]
267+
<< ", Final energy=" << final_energies[i] << "\n";
268+
}
269+
270+
// Parallel reduce: calculate total energy dissipated
271+
double total_energy_dissipated = diffeq::execution::patterns::parallel_reduce(
272+
final_energies.begin(), final_energies.end(),
273+
0.0,
274+
[](double acc, double energy) { return acc + (0.5 - energy); } // Initial energy was 0.5
275+
);
276+
277+
std::cout << "Total energy dissipated across all cases: " << total_energy_dissipated << "\n";
278+
279+
std::cout << "\n=== Enhanced Parallelism Integration Complete ===\n";
280+
std::cout << "The parallelism facade seamlessly integrates with existing diffeq integrators,\n";
281+
std::cout << "providing transparent acceleration for various computational patterns.\n";
282+
283+
return 0;
284+
}

0 commit comments

Comments
 (0)