First attempt at parallel programming failed

This is my attempt at parallel programming but it did not produce the same result as serial programming.

function mysquare(x::Float64)
    return x*x
end

function main()
    Result = Tuple[]
    for x in 1.0:100.0
        y = mysquare(x)
        push!(Result,(x,y))
    end
    SortedResult = sort(Result,lt=(x,y)->x[2]<y[2],rev=true)
    println(SortedResult[1])
    println(VERSION)
end

main()

with output

(100.0, 10000.0)
1.0.3

But my parallel attempt has failed to produce the same output

using SharedArrays
using Distributed
addprocs(4)

@everywhere function mysquare(x::Float64)
    return x*x
end

function main()
    Result = SharedArray{Float64,2}((100,2))
    @distributed for x in 1.0:100.0
        n = Int64(x)
        y = mysquare(x)
        Result[n,1] = x
        Result[n,2] = y
    end
    TupleResult = [ (Result[n,1],Result[n,2]) for n in 1:100 ]
    SortedResult = sort(TupleResult,lt=(x,y)->x[2]<y[2],rev=true)
    println(SortedResult[1])
    println(VERSION)
end

main()

Output

(0.0, 0.0)
1.0.3

I am not sure where I went wrong, I double check all my code and it looked correct.

1 Like

Try prefixing the loop with @sync.

@distributed spawns tasks on workers asynchronously and returns immediately.

You need to wait on the Future returned by @distributed or use @sync.

https://docs.julialang.org/en/v1/manual/parallel-computing/#Parallel-Map-and-Loops-1

2 Likes

Thanks for your advise. This code using @sync seems to work

using SharedArrays
using Distributed
addprocs(4)

@everywhere function mysquare(x::Float64)
    return x*x
end

function main()
    Result = SharedArray{Float64,1}(100)
    @sync @distributed for x in 1.0:100.0
        Result[Int64(x)] = mysquare(x)
    end
    TupleResult = [ (n,Result[n]) for n in 1:100 ]
    SortedResult = sort(TupleResult,lt=(x,y)->x[2]<y[2],rev=true)
    println(SortedResult[1])
    println(VERSION)
end

main()

output

(100, 10000.0)
1.0.3

Can someone explain why SharedArray cannot handle an array of tuple, forcing me to recreate the TupleResult to be consistent with the serial version of the program. Can the program work if I do not use the SharedArray? Is there another way of storing the result so that it can later be sorted to find the value I am interested in (aka the largest value) and the value of x that resulted in that value?

You can create a SharedArray of any bits type. In your example:

SharedArray{Tuple{Float64,Float64},1}(100)

If you just want the maximum value, you could use a “reducer” on the @distributed loop:

function main()
    result = @distributed max for x in 1.0 : 100.0
        (mysquare(x), x)
    end
    println(result)
    println(VERSION)
end

See this section of the manual: Parallel Computing · The Julia Language

1 Like

Thank you very much. This made my life a lot easier and speed up my computations