@@ -79,6 +79,61 @@ Now the launched task will *definitely* execute on worker 2 (or if it's not
79
79
possible to run on worker 2, Dagger will throw an error when you try to ` fetch `
80
80
the result).
81
81
82
+ ### Parallelize nested loops
83
+
84
+ Nested loops are a very common pattern in Julia, yet it's often difficult to
85
+ parallelize them efficiently with ` @threads ` or ` @distributed ` /` pmap ` .
86
+ Thankfully, this kind of problem is quite easy for Dagger to handle; here is an
87
+ example of parallelizing a two-level nested loop, where the inner loop
88
+ computations (` g ` ) depend on an outer loop computation (` f ` ):
89
+
90
+ ``` julia
91
+ @everywhere begin
92
+ using Random
93
+ Random. seed! (0 )
94
+
95
+ # Some "expensive" functions that complete at different speeds
96
+ const crn = abs .(randn (20 , 7 ))
97
+ f (i) = sleep (crn[i, 7 ])
98
+ g (i, j, y) = sleep (crn[i, j])
99
+ end
100
+ function nested_dagger ()
101
+ @sync for i in 1 : 20
102
+ y = Dagger. @spawn f (i)
103
+ for j in 1 : 6
104
+ z = Dagger. @spawn g (i, j, y)
105
+ end
106
+ end
107
+ end
108
+ ```
109
+
110
+ And the equivalent (and less performant) example with ` Threads.@threads ` ,
111
+ either parallelizing the inner or outer loop:
112
+
113
+ ``` julia
114
+ function nested_threads_outer ()
115
+ Threads. @threads for i in 1 : 20
116
+ y = f (i)
117
+ for j in 1 : 6
118
+ z = g (i, j, y)
119
+ end
120
+ end
121
+ end
122
+ function nested_threads_inner ()
123
+ for i in 1 : 20
124
+ y = f (i)
125
+ Threads. @threads for j in 1 : 6
126
+ z = g (i, j, y)
127
+ end
128
+ end
129
+ end
130
+ ```
131
+
132
+ Unlike ` Threads.@threads ` (which is really only intended to be used for a
133
+ single loop, unnested), ` Dagger.@spawn ` is capable of parallelizing across both
134
+ loop levels seamlessly, using the dependencies between ` f ` and ` g ` to determine
135
+ the correct order to execute tasks.
136
+
82
137
-----
83
138
84
139
## Quickstart: Data Management
0 commit comments