Juliaのマルチスレッドの問題

Aug 18 2020

コードの一部を並列化しようとしていますが、次の関数main1()とmain2()がJuliaのマルチスレッドを使用して異なる結果をもたらす理由がわかりません。

a = rand(4,4);b = rand(4,4);c = rand(4,4);d = rand(4,4)

function main1(a,b,c,d)
    L = zeros(2,2,16)
    FF = zeros(2,2,16)
    FT = zeros(2,2,16)
    F = Array{Float32}(undef,2,2)
    # L = Array{Array{Float32, 1}, 4}

    for i = 1:4
        for j = 1:4
            ic = i + j*(i-1)
            F[1,1] = a[i,j]
            F[1,2] = b[i,j]
            F[2,1] = c[i,j]
            F[2,2] = d[i,j]
            L[:,:,ic] .= F * F'
            FF[:,:,ic] .= F
            FT[:,:,ic] .= F'
        end
    end
    return L,FF,FT
end

function main2(a,b,c,d)

    L  = zeros(2,2,16)
    FF = zeros(2,2,16)
    FT = zeros(2,2,16)
    F  = Array{Float32}(undef,2,2)
    # L = Array{Array{Float32, 1}, 4}

    Threads.@threads for i = 1:4
        Threads.@threads for j = 1:4
            ic = i + j*(i-1)
            F[1,1] = a[i,j]
            F[1,2] = b[i,j]
            F[2,1] = c[i,j]
            F[2,2] = d[i,j]
            L[:,:,ic] .= F * F'
            FF[:,:,ic] .= F
            FT[:,:,ic] .= F'
        end
    end
    return L,FF,FT
end

main1()の並列化を適切に修正するにはどうすればよいですか?

回答

1 PrzemyslawSzufel Aug 18 2020 at 23:44

@threadsループをネストすることはできないため、通常は次のようにします。

Threads.@threads for u in vec(CartesianIndices((4,4)))
    i,j = u.I
    # your code goes here
end

ただし、コードでは、のic値の異なるペアに対して同じ値を取得します(i,j)。ではmain1、あなたは、同じ部分上書きされLFFFT明らかにバグで何回も。マルチスレッドは、データが上書きされる順序を変更するため、異なる結果が得られます。結論として、最初に修正main1してから並列化します。