@@ -79,6 +79,61 @@ Now the launched task will *definitely* execute on worker 2 (or if it's not
7979possible to run on worker 2, Dagger will throw an error when you try to ` fetch `
8080the result).
8181
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+
82137-----
83138
84139## Quickstart: Data Management
0 commit comments