对于这个简单的Julia代码,如何达到最佳并行效率?

时间:2020-02-07 17:47:01

标签: multithreading julia vectorization

我有以下简单代码:

function hamming4(bits1::Integer, bits2::Integer)
    return count_ones(bits1 ⊻ bits2)
end

function random_strings2(n, N)
    mask = UInt128(1) << n - 1
    return [rand(UInt128) & mask for i in 1:N]
end




function find_min(strings, n, N)
    minsofar = fill(n, Threads.nthreads())
    # minsofar = n
    Threads.@threads for i in 1:N 
    # for i in 1:N
        for j in i+1:N
            dist = hamming4(strings[i], strings[j])
            if dist < minsofar[Threads.threadid()]
                    minsofar[Threads.threadid()] = dist

            end
        end
    end
    return minimum(minsofar)
    #return minsofar
end


function ave_min(n, N)
    ITER = 10
    strings = random_strings2(n, N)
    new_min = find_min(strings, n, N)
    avesofar = new_min
    # print("New min ", new_min, ". New ave ", avesofar, "\n")
    total = avesofar
    for i in 1:ITER-1
        strings = random_strings2(n, N)
        new_min = find_min(strings, n, N)
        avesofar = avesofar*(i/(i+1)) + new_min/(i+1)
        print("Iteration ", i, ". New min ", new_min, ". New ave ", round(avesofar; digits=2), "\n")
    end
    return avesofar
end

N = 2^16
n = 99

print("Overall average ", ave_min(n, N), "\n")

当我在Linux上的AMD 8350上运行时,CPU使用率约为430%(而不是接近800%)。

是否可以使并行化工作更有效率?

我还注意到了一个名为LoopVectorization.jl的外观非常新的软件包。当我以一种可向量化的方式计算the Hamming distance时,是否也可以以此方式加快代码的速度?

可以使用LoopVectorization.jl对代码进行矢量化吗?

(我对Julia完全陌生)

1 个答案:

答案 0 :(得分:4)

代码的并行化似乎是正确的。

您很有可能在Atom或其他IDE中运行它。默认情况下,Atom仅使用一半的核心(更确切地说,仅使用物理而非逻辑核心)。

例如在我的计算机上的Atom中运行:

julia> Threads.nthreads()
4

您需要做的是显式设置JULIA_NUM_THREADS

Windows命令行(仍假设8个逻辑内核)

set JULIA_NUM_THREADS=8

Linux命令行

export JULIA_NUM_THREADS=8

这样做之后,您的代码将占据我所有内核的100%。

编辑

讨论之后-通过使用Distributed而不是Threads,您可以将时间减少到单线程时间的20%左右,因为这样可以避免内存共享:

代码大致如下所示:

using Distributed
addprocs(8)

@everywhere function hamming4(bits1::Integer, bits2::Integer)
    return count_ones(bits1 ⊻ bits2)
end

function random_strings2(n, N)
    mask = UInt128(1) << n - 1
    return [rand(UInt128) & mask for i in 1:N]
end

function find_min(strings, n, N)
    return @distributed (min) for i in 1:N-1
        minimum(hamming4(strings[i], strings[j]) for j in i+1:N)
    end
end

### ... the rest of code remains unchanged 
相关问题