Julia 没有使用所有可用的 CPU 线程

Kim*_*Kim 4 performance benchmarking multithreading numpy julia

我在 Julia 中进行了一些计算,并注意到它的运行速度明显比 numpy慢(大约25倍!)。

然后我意识到 Julia 只在我的 PC 上使用了总共96 个CPU 线程(48 个物理内核)中的8 个线程,而 numpy 似乎在使用超过70 个线程时没有问题。

与运行朱莉娅$julia --thread 96 说法并不能使即使任何区别julia> Threads.nthreads()的回报96

此外,对结果有点失望的是,我怀疑 Julia 使用所有 96 个线程仍然可能无法与 numpy 的速度相匹配。

这是朱莉娅代码。我简单地测量与时间julia> @time calc_fid(mat_a, mat_b)这给了我90秒的平均水平。

using Statistics
using LinearAlgebra

function calc(A::Array{Float32,2}, B::Array{Float32,2})
    ?_A = mean(A, dims=2)
    ?_B = mean(B, dims=2)
    ?_A = cov(A, dims=2)
    ?_B = cov(B, dims=2)

    ssdiff = sum((?_A - ?_B).^2)
    covmean = sqrt(?_A * ?_B)
    res = ssdiff + tr(?_A .+ ?_B .- 2.0 * covmean)
    
    return res
end
Run Code Online (Sandbox Code Playgroud)

这是平均需要大约3.5秒的 numpy 代码。用time.perf_counter()

using Statistics
using LinearAlgebra

function calc(A::Array{Float32,2}, B::Array{Float32,2})
    ?_A = mean(A, dims=2)
    ?_B = mean(B, dims=2)
    ?_A = cov(A, dims=2)
    ?_B = cov(B, dims=2)

    ssdiff = sum((?_A - ?_B).^2)
    covmean = sqrt(?_A * ?_B)
    res = ssdiff + tr(?_A .+ ?_B .- 2.0 * covmean)
    
    return res
end
Run Code Online (Sandbox Code Playgroud)

任何建议/解释将不胜感激!

cbk*_*cbk 5

您的 Julia 示例代码实际上并未使用 Julia 的多线程功能。

在 Julia 中,如果您想要多线程,通常需要显式启用它。像meancov不会自动成为多线程的函数,仅仅因为以多线程启动 Julia;如果您希望这些函数是多线程的,您将需要编写它们的多线程版本,或者使用已经这样做的包。

您的 Julia 示例代码中唯一会像当前编写的那样多线程的是线性代数,因为它回退到BLAS(确实很可能是 numpy),它有自己的多线程系统,与 Julia 的多线程完全分开(BLAS 是用 Fortran 编写)。不过,这也可能没有使用所有 96 个线程,并且在您的情况下几乎可以肯定默认为 8 个。 可以检查 Julia 中 BLAS 使用的线程数

using LinearAlgebra
BLAS.get_num_threads()
Run Code Online (Sandbox Code Playgroud)

或类似地设置

BLAS.set_num_threads(n)
Run Code Online (Sandbox Code Playgroud)