gpt4 book ai didi

performance - 随机微分方程的疯狂空间分配求解系统

转载 作者:行者123 更新时间:2023-12-04 02:40:31 25 4
gpt4 key购买 nike

第一次在这里提问。我之前使用一个简单的 MATLAB 脚本对 90 个 Hopf 振荡器进行建模,通过矩阵与 randn 噪声以及简单的欧拉步积分进行耦合。我想升级这个,所以我进入了 Julia,似乎有很多令人兴奋的特性。

This is the system of equations I'm solving

我有点迷失了。我开始使用 Differentialequations.jl(随机求解器),找到了一个解决方案,并发现自己的基准告诉我,求解 200 秒占用了 4 GB 的空间! (2.5 Gb,alg_hints=[:stiff])(我还没有修复 dt,之前我使用 dt=0.1)

function Shopf(du,u,p,t)

du[1:90,1]=(p[1:90,1]-u[1:90,1].^2.0-u[1:90,2].^2.0).*u[1:90,1]-p[1:90,2].*u[1:90,2] + 0.5*(-p[: , end].*u[:,1]+p[:,4:end-1] *u[:,1])
du[1:90,2]=(p[1:90,1]-u[1:90,1].^2.0-u[1:90,2].^2.0).*u[1:90,1]+p[1:90,2].*u[1:90,1] + 0.5*(-p[: , end].*u[:,2]+p[:,4:end-1] *u[:,2])

end


function σ_Shopf(du,u,p,t)

du[1:90,1]=0.04*ones(90,1)
du[1:90,2]=0.04*ones(90,1)


end


#initial condition
u0=-0.1*ones(90,2);
#initial time
t0=0.0;
#final time
tend=200.0;
#setting parameter matrix
p0=[0.1 , 2*pi*0.04]
push!(p0,-p0[2])
p=p0'.*ones(90,3);
SC=SC;
p=[p SC]
p=[p sum(SC,dims=2)]
#


#col 1 :alpha
#col 2-3 : [w0 -w0]

#col 3-93 : coupling matrix
#col 94: col-wise sum of coupling matrix


@benchmark solve(prob_sde_Shopf,nlsolver=Rosenbrock23(),alg_hints=[:stiff])

BenchmarkTools.试用版: 内存估计:2.30 GiB

分配估计:722769


最短时间:859.224 ms (13.24% GC)

中位时间:942.707 毫秒(13.10% GC)

平均时间:975.430 毫秒(12.99% GC)

最长时间:1.223 s (13.00% GC)


样本:6

评估/样本:1

有什么想法吗?我正在检查几种解决方案,但它们都没有将内存量减少到合理的数量。提前致谢。

最佳答案

您正在创建数量惊人的临时数组。每个切片都会创建一个临时的。您到处添加一个点,但您必须所有内容都添加点才能获得融合广播。相反,您只需使用 @. 宏即可为您完成此操作。另外,使用 @views 将确保切片不会复制:

function Shopf(du, u, p, t)
@. du[1:90, 1] = @views (p[1:90, 1] - u[1:90, 1]^2 - u[1:90, 2]^2) * u[1:90, 1] -
p[1:90, 2] * u[1:90,2] + 0.5 * (-p[:, end] * u[:, 1] + p[:, 4:end-1] * u[:,1])
@. du[1:90, 2] = @views (p[1:90, 1] - u[1:90, 1]^2 - u[1:90, 2]^2) * u[1:90, 1] +
p[1:90, 2] * u[1:90,1] + 0.5 * (-p[:, end] * u[:, 2] + p[:, 4:end-1] * u[:,2])
end

另外,不要写x^2.0,使用x^2,前者是慢速 float 幂,而后者是快速x * x 。事实上,尽可能地尝试使用整数,例如乘法、加法等。

还有一件事

function σ_Shopf(du,u,p,t)

du[1:90,1]=0.04*ones(90,1)
du[1:90,2]=0.04*ones(90,1)


end

无需在赋值的右侧创建两个临时数组。只需这样写:

function σ_Shopf(du, u, p, t)
du[1:90, 1:2] .= 0.04
end

更快更简单。请注意,我尚未对此进行测试,因此请修复任何拼写错误。

(最后,请使用缩进并在运算符周围放置空格,这会使您的代码更易于阅读。)

更新:我真的不知道你的代码应该做什么,用奇怪的索引做什么,但这里有一个可能的改进,只使用循环(我认为这实际上更干净,并且可以让您进行进一步的优化):

产生 A 的操作是矩阵乘积,因此您无法避免在那里进行分配,除非您可以使用 mul! 传入要处理的缓存数组。除此之外,您不应有以下分配。

function shopf!(du, u, p, t)
A = @view p[:, 4:end-1] * u
# mul!(A, view(p, 4:end-1), u) # in-place matrix product
for i in axes(u, 1)
val = (p[i, 1] - u[i, 1]^2 - u[i, 2]^2) * u[i, 1] # don't calculate this twice
du[i, 1] = val - (p[i, 2] * u[i, 2]) - (0.5 * p[i, end] * u[i, 1]) +
(0.5 * A[i, 1])
du[i, 2] = val + (p[i, 2] * u[i, 1]) - (0.5 * p[i, end] * u[i, 2]) +
(0.5 * A[i, 2])
end
end

在此之后,您可以添加各种优化,@inbounds(如果您确定数组大小)、多线程、@simd 甚至 @avx 来自 LoopVectorization 实验包。

关于performance - 随机微分方程的疯狂空间分配求解系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61703598/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com