multithreading - 通过并行化提高循环性能
问题描述
所以我试图围绕 Julia 的并行化选项。我将随机过程建模为马尔可夫链。由于链是独立的复制,外部循环是独立的 - 使问题令人尴尬地并行。我尝试实现 a@distributed
和@threads
解决方案,两者似乎都运行良好,但并不比顺序快。
这是我的代码的简化版本(顺序):
function dummy(steps = 10000, width = 100, chains = 4)
out_N = zeros(steps, width, chains)
initial = zeros(width)
for c = 1:chains
# print("c=$c\n")
N = zeros(steps, width)
state = copy(initial)
N[1,:] = state
for i = 1:steps
state = state + rand(width)
N[i,:] = state
end
out_N[:,:,c] = N
end
return out_N
end
将这个问题并行化以提高性能的正确方法是什么?
解决方案
这是正确的方法(在撰写此答案时,另一个答案不起作用-请参阅我的评论)。
我将使用比问题中稍微简单的示例(但非常相似)。
1.非并行化版本(基线场景)
using Random
const m = MersenneTwister(0);
function dothestuff!(out_N, N, ic, m)
out_N[:, ic] .= rand(m, N)
end
function dummy_base(m=m, N=100_000,c=256)
out_N = Array{Float64}(undef,N,c)
for ic in 1:c
dothestuff!(out_N, N, ic, m)
end
out_N
end
测试:
julia> using BenchmarkTools; @btime dummy_base();
106.512 ms (514 allocations: 390.64 MiB)
2. 与线程并行
#remember to run before starting Julia:
# set JULIA_NUM_THREADS=4
# OR (Linux)
# export JULIA_NUM_THREADS=4
using Random
const mt = MersenneTwister.(1:Threads.nthreads());
# required for older Julia versions, look still good in later versions :-)
function dothestuff!(out_N, N, ic, m)
out_N[:, ic] .= rand(m, N)
end
function dummy_threads(mt=mt, N=100_000,c=256)
out_N = Array{Float64}(undef,N,c)
Threads.@threads for ic in 1:c
dothestuff!(out_N, N, ic, mt[Threads.threadid()])
end
out_N
end
让我们测试一下性能:
julia> using BenchmarkTools; @btime dummy_threads();
46.775 ms (535 allocations: 390.65 MiB)
3. 与进程并行(在单台机器上)
using Distributed
addprocs(4)
using Random, SharedArrays
@everywhere using Random, SharedArrays, Distributed
@everywhere Random.seed!(myid())
@everywhere function dothestuff!(out_N, N, ic)
out_N[:, ic] .= rand(N)
end
function dummy_distr(N=100_000,c=256)
out_N = SharedArray{Float64}(N,c)
@sync @distributed for ic in 1:c
dothestuff!(out_N, N, ic)
end
out_N
end
性能(请注意,进程间通信需要一些时间,因此对于小型计算线程通常会更好):
julia> using BenchmarkTools; @btime dummy_distr();
62.584 ms (1073 allocations: 45.48 KiB)
推荐阅读
- java - @PersistenceContext 不适用于参数。如何通过构造函数注入 EntityManager?
- java - 在指定路径上找不到 .jks 文件
- java - java中带有双反斜杠的正则表达式
- c# - 停止上一个任务并运行新任务 wpf
- asp.net - 使用 ASP.Net 直接打印 PDF 文件
- node.js - 使用 Typescript 在 Sequelize 模型中创建实例方法
- javascript - CSharp 和 javascript 中的 FromXmlString
- vba - exel文件中的错误行
- sql-server - SQL Server:查询单个表以显示其他列
- ios - 如何将用户注册到 AWSCognitoIdentityUserPool 并取回 JWT 令牌?