# Advice for parallel computation

**URL:** <https://discourse.julialang.org/t/advice-for-parallel-computation/60087>\
**Category:** General Usage\
**Created:** [April 27, 2021, 8:03am UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087 "2021-04-27T08:03:55Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [April 27, 2021, 8:03am UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087/1 "2021-04-27T08:03:55Z")

</div>

Hi,

I am trying to solve a big PDE, and I want to parallelize a finite difference. I am seeking some advice on how to do this.

At some point I do the following

```julia
using PDEPackage
# struct that contains the parameters
pde = PDEPackage.PDE()
# compute difference
sol1 = rand(100); sol2 = rand(100)
dsol = pde(sol1) - pde(sol2) 

```

The computation of `pde(sol)` takes minutes. Hence, I am considering using distributed computing. One issue I have is that `pde` is a callable struct with overwritten internal field upon call `pde(sol)`. So I wil need to duplicate the internal data.

I am considering doing the following

```julia
pde1 = pde
pde2 = deepcopy(pde)
data = [(pde1, sol1), (pde2, sol2)]
result = pmap(x -> x[1](x[2]), data)
dsol = result[1] - result[2]

```

Does anyone has better suggestion?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 27, 2021, 8:16am UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087/2 "2021-04-27T08:16:53Z")

</div>

[Threaded Assembly · Ferrite.jl](https://ferrite-fem.github.io/Ferrite.jl/dev/examples/threaded_assembly/) has a small example of a parallel FEM computation. And each thread has its own “`ScratchValues`” which is data that the thread owns and can mutate freely: [Threaded Assembly · Ferrite.jl](https://ferrite-fem.github.io/Ferrite.jl/dev/examples/threaded_assembly/#Threaded-data-structures). So it is quite similar to what you consider.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [April 27, 2021, 10:02am UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087/3 "2021-04-27T10:02:14Z")

</div>

Here some course notes to do finite-diff on the GPU (or threaded CPU): [https://github.com/luraess/geo-hpc-course](https://github.com/luraess/geo-hpc-course) . Maybe good for inspiration.

---

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [April 27, 2021, 7:22pm UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087/4 "2021-04-27T19:22:21Z")

</div>

Thank you for your suggestions!

It took me some time to analyse your answers. I forgot to mention that I am targeting distributed computing because each `pde` is threaded. I guess I will have to modify @kristoffer.carlsson suggestion.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [April 27, 2021, 7:46pm UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087/5 "2021-04-27T19:46:51Z")

</div>

> [@kristoffer.carlsson](#):
>
> And each thread has its own “ `ScratchValues` ” which is data that the thread owns and can mutate freely: [Threaded Assembly · Ferrite.jl](https://ferrite-fem.github.io/Ferrite.jl/dev/examples/threaded_assembly/#Threaded-data-structures).

Just FYI, the idiom `scratches[Threads.threadid()]` only works with `Threads.@threads for` (i.e., not with `Threads.@spawn`) and it also relies on the implementation detail of `Threads.@threads`. It’s possible that this idiom stops working at some point (though maybe we’d need to keep it as-is, given that many programs rely on it). I discussed this a bit in [FAQ · FLoops](https://juliafolds.github.io/FLoops.jl/dev/explanation/faq/#faq-state-threadid)

For new _library_ functions, I suggest avoiding this idiom.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 27, 2021, 8:19pm UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087/6 "2021-04-27T20:19:19Z")

</div>

> [@tkf](#):
>
> and it also relies on the implementation detail of `Threads.@threads` .

From what I understand, you will be able to set the scheduler to `static` “which creates one task per thread and divides the iterations equally among them.”.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [April 27, 2021, 8:44pm UTC](https://discourse.julialang.org/t/advice-for-parallel-computation/60087/7 "2021-04-27T20:44:29Z")

</div>

Yes, that’s why said library code. Library functions cannot use `:static` since they can be called from any task. I think it’s OK to use `scratches[Threads.threadid()]` application/script code since you can control how the functions using `@threads :static` are called. But, I think it also makes sense to avoid `scratches[Threads.threadid()]` even in script code since `@threads :static` makes it impossible to nest your function into parallel higher-order functions (e.g., you may want to parallel map over some inputs using your parallel function).
