Parrallel programming with Distributed Arrays

please I need help, I'm trying to do this equation in parallel but it is not working can someone tell what's wrong? thanks

#Heat Equation
#Numerical Solution
using Distributed
addprocs(4)
@everywhere using LinearAlgebra
@everywhere using DistributedArrays
using Plots
@everywhere c = 10
@everywhere dx = 0.1
@everywhere dt = 0.01
@everywhere gm = dt/(c*(dx^2))
@everywhere 1/gm

if gm <= 1/2 
@everywhere x = 0:dx:1
    @everywhere t = 0:dt:5
    @everywhere row = length(t)
    @everywhere col = length(x)
    U=ones(row,col)
    U[:,end] .= 0
    U[:,1] .= 0
    U = distribute(U; dist=(2,1))
    @sync @distributed for k = 1:length(x)
        U_local =localpart(U)
        U_local[1,k] = 10*sin.(pi*x[k])
    end
    @sync @distributed for i = 1:row-1
        for n = 2:col-1
            U_local[i+1,n] = gm*(U_local[i,n+1] + U_local[i,n-1]) + @.(1-2*gm)*(U_local[i,n])
        end
    end
else
    println("nicht möglich")
end
U

Perhaps you’re not using the local indices of the array on each worker? I obtain this error:

ERROR: TaskFailedException:
On worker 4:
BoundsError: attempt to access 0×0 Array{Float64,2} at index [1, 7]

and the indices appear to be

julia> @fetchfrom 2 localindices(U)
(1:251, 1:11)

julia> @fetchfrom 3 localindices(U)
(252:501, 1:11)

julia> @fetchfrom 4 localindices(U)
(1:0, 1:0)

Clearly there’s nothing on the 4th worker, as is expected. Perhaps you want something like this?

if gm <= 1/2 
    @everywhere x = 0:dx:1
    @everywhere t = 0:dt:5
    @everywhere row = length(t)
    @everywhere col = length(x)
    U=ones(row,col)
    U[:,end] .= 0
    U[:,1] .= 0
    U = distribute(U; dist=(2,1))
    @sync @distributed for k = localindices(U)[2]
        U_local =localpart(U)
        U_local[1,k] = 10*sin.(pi*x[k])
    end
    @sync @distributed for i = localindices(U)[1][2:end-1]
        for n = localindices(U)[2]
            U_local[i+1,n] = gm*(U_local[i,n+1] + U_local[i,n-1]) + @.(1-2*gm)*(U_local[i,n])
        end
    end
else
    println("nicht möglich")
end

I haven’t checked to see if this produces the correct result.

Hello! Thank you so much I have tried it but it returns me the same DArray without an update.

I added only 2 processes, not 4, that was a mistake

Looking more into your code, you’re splitting the array in time across processors. However the time evolution is sequential, so I’m not sure if this is the best approach? You should split the spatial domain into parts. Additionally you will be exchanging data across processors, so you need to ensure that they are in sync.

Before you think about parallel programming in this case (I think it’s some kind of university assignment, studied physics myself) you should do some other things:

  1. Break up your code into functions, e.g. write a function for the laplace operator, for initialization etc.
  2. For good performance, keep in mind that julia’s array indexing is column major (leftmost index increments the fastest). So indexing should be U[x,t], as you access all places before you advance in time.
  3. There are two ways of solving the heat equation: one where you use only old values to calculate the next timestep and a second one where your laplace operator goes through the array and uses both, old and new values. The latter is more accurate as far as i remember, but also annoying to parallelize. So if you really want to push it, go with the former first.
  4. Take a look at sciml.ai and their tutorials, as well as DifferentialEquations.jl.
1 Like

please how can I sycronilise them?