宏’@spwan‘会将后面的表达式自动分配给一个Worker进行计算,假设f()
是一个计算密集型的任务,需要计算n次,目前只有m个Worker,且m<n。
如果一次使用for
和@spawn f()
分配全部的任务计算所需时间和
自己写一个分配任务的函数,有Worker空闲时就分配任务,使正在运行的任务数量始终为m。这样完成全部任务所需的时间相比,那个更快?
可能是我的问题太偏了吧,没有人回答,最终我自己来解决了。
我写了以下代码,一个是直接分配所有100个任务;一个是对完成任务的空闲进程分配任务,直到完成所有100个任务为止,得到的结果是二者执行效率几乎一样。
这是我写的代码:
using Distributed
addprocs(4)
@everywhere function long_compute(size::Int64)
x = zeros(Float64, 10^size)
for i in 1:10^size
x[i] = rand()
end
sum(x)
end
function saturated(bin::Int64)
workers_l = []
result = zeros(Float64, bin)
for i in 1:bin
push!(workers_l, @spawn long_compute(8))
end
for i in 1:bin
result[i] = fetch(workers_l[i])
end
sum(result)/bin
end
function self_manger(bin::Int64)
numof_workers = length(workers())
result = zeros(Float64, bin)
workers_l = [Future(1) for i in 1:numof_workers]
# 记录完成任务ID在列表中的位置
c = Channel{Int64}(numof_workers)
for i in 1:numof_workers
@async put!(workers_l[i], remotecall_fetch(long_compute, workers()[i], 8)) & put!(c, i)
end
# i记录了下次数据在result中存放的位置
# (i - 1)即为已经记录的数据数量
# 并且(i - 1 + numof_workers)为已经启动的进程数
# 当已经启动的进程数量小于bin时,不断记录已经完成任务的进程的结果,并在完成任务的进程再启动完成任务
# 当启动bin数量的进程后,等待剩余正在运行的进程并返回结果
i = 1
while (i - 1 + numof_workers) < bin
j = take!(c)
result[i] = fetch(workers_l[j])
workers_l[j] = Future(1)
@async put!(workers_l[j], remotecall_fetch(long_compute, workers()[j], 8)) & put!(c, j)
i = i + 1
end
while i <= bin
j = take!(c)
result[i] = fetch(workers_l[j])
workers_l[j] = Future(1)
i = i + 1
end
close(c)
sum(result)/bin
end
versioninfo()
@time saturated(100)
@time saturated(100)
@time self_manger(100)
@time self_manger(100)
这是输出:
Julia Version 1.3.1
Commit 2d5741174c (2019-12-30 21:36 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Genuine Intel(R) CPU 0000 @ 2.90GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.1 (ORCJIT, skylake)
Environment:
JULIA_EDITOR = "C:\Users\WeiM\AppData\Local\atom\app-1.45.0\atom.exe" -a
JULIA_NUM_THREADS = 6
36.427815 seconds (1.85 M allocations: 91.499 MiB, 0.03% gc time)
34.688984 seconds (14.32 k allocations: 534.688 KiB)
35.655838 seconds (385.08 k allocations: 19.315 MiB, 0.04% gc time)
34.962047 seconds (13.41 k allocations: 523.938 KiB)