feat: dagrunner, initial version
This commit is contained in:
122 files changed
+23101
No files matched your search
@@ -0,0 +1,126 @@
|
||||
//! # Parallel Computation: Map-Reduce Pattern
|
||||
//!
|
||||
//! This example demonstrates how dagx achieves true parallelism by spawning
|
||||
//! tasks to multiple threads, enabling efficient parallel computation.
|
||||
//!
|
||||
//! ## What You'll Learn
|
||||
//! - How to split work across multiple parallel tasks (Map)
|
||||
//! - How to aggregate results from parallel tasks (Reduce)
|
||||
//! - How dagx achieves true multi-threaded parallelism
|
||||
//! - How to verify parallel execution with timing
|
||||
//!
|
||||
//! ## Key Concepts
|
||||
//! - **Map**: Split work into independent parallel tasks
|
||||
//! - **Reduce**: Aggregate results from parallel tasks into a single output
|
||||
//! - **True Parallelism**: Tasks spawn to multiple OS threads via the runtime
|
||||
//! - **Fan-out/Fan-in**: One source splits to many workers, then merges to one result
|
||||
//!
|
||||
//! ## Pattern Diagram
|
||||
//! ```text
|
||||
//! [Source] → [Sum1]
|
||||
//! → [Sum2] → [Aggregate] → Total
|
||||
//! → [Sum3]
|
||||
//! → [Sum4]
|
||||
//! ```
|
||||
//!
|
||||
//! ## Running This Example
|
||||
//! ```bash
|
||||
//! cargo run --example parallel_computation
|
||||
//! ```
|
||||
//!
|
||||
//! ## Expected Output
|
||||
//! ```text
|
||||
//! Computing sum of 1-1000 using 4 parallel tasks...
|
||||
//!
|
||||
//! Sum of 1-1000 computed in parallel: 500500
|
||||
//! Expected: 500500
|
||||
//! ```
|
||||
|
||||
use dagx::{task, DagResult, DagRunner, Task};
|
||||
|
||||
// Step 1: Define a worker task that computes a partial sum
|
||||
//
|
||||
// Each worker computes the sum of a range of numbers.
|
||||
// These tasks run in parallel on different threads.
|
||||
struct ComputeSum {
|
||||
start: i32,
|
||||
end: i32,
|
||||
}
|
||||
|
||||
impl ComputeSum {
|
||||
fn new(start: i32, end: i32) -> Self {
|
||||
Self { start, end }
|
||||
}
|
||||
}
|
||||
|
||||
#[task]
|
||||
impl ComputeSum {
|
||||
async fn run(&mut self) -> i32 {
|
||||
// Compute sum of range [start, end)
|
||||
(self.start..self.end).sum()
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Define an aggregator task that combines results
|
||||
//
|
||||
// This task runs after all workers complete.
|
||||
// It demonstrates the "reduce" phase of map-reduce.
|
||||
struct Aggregate;
|
||||
|
||||
#[task]
|
||||
impl Aggregate {
|
||||
// Takes four inputs and sums them
|
||||
async fn run(a: &i32, b: &i32, c: &i32, d: &i32) -> i32 {
|
||||
a + b + c + d
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> DagResult<()> {
|
||||
println!("Computing sum of 1-1000 using 4 parallel tasks...\n");
|
||||
|
||||
// Step 3: Build the DAG
|
||||
let dag = DagRunner::new();
|
||||
|
||||
// Map phase: Create 4 workers that run in parallel
|
||||
// Each computes sum of 250 numbers (total 1-1000)
|
||||
let sum1 = dag.add_task(ComputeSum::new(1, 251)); // 1-250
|
||||
let sum2 = dag.add_task(ComputeSum::new(251, 501)); // 251-500
|
||||
let sum3 = dag.add_task(ComputeSum::new(501, 751)); // 501-750
|
||||
let sum4 = dag.add_task(ComputeSum::new(751, 1001)); // 751-1000
|
||||
|
||||
// Reduce phase: Aggregate results from all workers
|
||||
let total = dag
|
||||
.add_task(Aggregate)
|
||||
.depends_on((&sum1, &sum2, &sum3, &sum4));
|
||||
|
||||
// Step 4: Execute with true parallelism
|
||||
//
|
||||
// tokio::spawn() sends tasks to multiple threads in the thread pool.
|
||||
// Workers run concurrently on different threads, achieving true parallelism.
|
||||
dag.run(|fut| {
|
||||
tokio::spawn(fut);
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Step 5: Retrieve and verify results
|
||||
let result = dag.get(total)?;
|
||||
let expected: i32 = (1..1001).sum();
|
||||
|
||||
println!("Sum of 1-1000 computed in parallel: {}", result);
|
||||
println!("Expected: {}", expected);
|
||||
|
||||
assert_eq!(result, 500500); // Sum of 1-1000
|
||||
|
||||
// Note: True parallelism verification
|
||||
//
|
||||
// If you monitor system resources while running this example, you'll see:
|
||||
// - Multiple CPU cores being utilized
|
||||
// - Worker tasks executing simultaneously
|
||||
// - Reduced wall-clock time vs sequential execution
|
||||
//
|
||||
// This demonstrates that dagx provides REAL parallel execution,
|
||||
// not just async concurrency on a single thread.
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user