【问题标题】:Tricks to improve the performance of a cunstom function in Julia提高 Julia 中自定义函数性能的技巧
【发布时间】:2021-04-03 01:05:11
【问题描述】:

我正在使用 Julia 复制最初在 Matlab 中制作的一系列步骤。在 Octave 中,此过程需要 1.4582 秒,而在 Julia(使用 Jupyter)中,大约需要 10 秒。我会尽量在脚本中保持简短。我的目标是达到或提高 Octave 的性能。首先,我将描述我的变量和一些函数:

  1. zgrid(双 1x7 尺寸)
  2. kgrid(双倍 500x1 尺寸)
  3. V0(双倍 500x7 尺寸)
  4. P(双 7x7 大小)一个转换矩阵
  5. delta 和 beta 是固定参数。
  6. F(z,k) 和 u(c) 是特殊函数,在 Julia 脚本中指定。
% Octave script
% V0 is given
[K, Z, K2] = meshgrid(kgrid, zgrid, kgrid);
K = permute(K, [2, 1, 3]);
Z = permute(Z, [2, 1, 3]);
K2 = permute(K2, [2, 1, 3]);

C = max(f(Z,K) + (1-delta)*K - K2,0);
U = u(C);

EV = V0*P';% EV is a 500x7 matrix size
EV = permute(repmat(EV, 1, 1, 500), [3, 2, 1]);
H = U + beta*EV;
[TV, index] = max(H, [], 3);

在 Julia 中,我创建了一个复制此过程的函数。我使用了循环,但它的性能要长 9 倍。

% Julia script
% V0 is the input of my T operator function
V0 = repeat(sqrt.(kgrid), outer = [1,7]);
F = (z,k) ->  exp(z)*(k^α);
u = (c) -> (c^(1-μ) - 1)/(1-μ)

% parameters
α = 1/3
β = 0.987
δ = 0.012;
μ = 2
Kss = 48.1905148382166
kgrid = range(0.75*Kss, stop=1.25*Kss, length=500);
zgrid = [-0.06725382459813659, -0.044835883065424395, -0.0224179415327122, 0 , 0.022417941532712187, 0.04483588306542438, 0.06725382459813657]

function T(V)
    E=V*P'
    T1 = zeros(Float64, 500, 7 )
    aux = zeros(Float64, 500)
    for i = 1:7
        for j = 1:500
            for l = 1:500
                c= maximum( (F(zrid[i],kgrid[j]) +(1-δ)*kgrid[j] - kgrid[l],0))
                aux[l] =  u(c) + β*E[l,i]
            end
            T1[j,i] = maximum(aux)     
        end
    end
    return T1
end

我非常想提高我在 Julia 中的表现。我相信有办法改进,但我是 Julia 编程新手。

【问题讨论】:

  • 您的 Julia 代码有错误。括号不匹配
  • 另外,为什么aux 的长度为5000,而您似乎只访问它的第一个500 元素?
  • 另外,kgridzrid 是在哪里定义的?
  • 如果它们是global 变量,那可能是问题的一部分
  • u 和 F 函数取决于其他校准参数。为了不加载脚本,我决定不完全指定它们。

标签: performance matlab julia


【解决方案1】:

此代码在 5 毫秒内为我运行。请注意,我已将 Fu 设置为适当的(非匿名)函数 F_u_,但您可以通过创建匿名函数 const 来获得类似的效果。

您的主要问题是您有很多非const 全局变量,并且您的主函数多次执行不必要的工作,并创建了一个不必要的数组aux

手册中的性能提示部分是必不可少的阅读:https://docs.julialang.org/en/v1/manual/performance-tips/

F_(z,k) = exp(z) * (k^(1/3));  # you can still use α, but it must be const
u_(c) = (c^(1-2) - 1)/(1-2)

function T_(V, P, kgrid, zgrid, β, δ)
    E = V * P'
    T1 = similar(V)
    for i in axes(T1, 2)
        for j in axes(T1, 1)
            temp = F_(zgrid[i], kgrid[j]) + (1-δ)*kgrid[j]
            aux = -Inf
            for l in eachindex(kgrid)
                c = max(0.0, temp - kgrid[l])
                aux = max(aux, u_(c) + β * E[l, i])
            end
            T1[j,i] = aux
        end
    end
    return T1
end

基准测试:

V0 = repeat(sqrt.(kgrid), outer = [1,7]);
zgrid = sort!(rand(1, 7); dims=2)
kgrid = sort!(rand(500, 1); dims=1)
P = rand(length(zgrid), length(zgrid))
@btime T_($V0, $P, $kgrid, $zgrid, $β, $δ);
# output:   5.126 ms (4 allocations: 54.91 KiB)

【讨论】:

  • 这是一个很好的解决方案。现在我正在尝试迭代 T_ 函数,但我做错了。首先,我声明了一定的公差“tol”,并设置了 dist = tol +1。所以,当 dist> 容差时,做 V1 = T_ (V0); dist = 距离(V1,V0); V0 = V1。但这需要太长时间。我认为这个新问题的解决方案是添加一个while循环并修改上面的代码。你认为我应该创建一个新问题吗?我整天都在想,我无法优化。我的远程函数是:最大值(abs.(V1 - V0))。
  • 不知道为什么这会花很长时间,但请确保避免使用全局变量,将外部循环包装在函数中,将变量作为输入参数传递,并彻底阅读性能提示。如果它仍然很慢,我会提出一个新问题。 (你的距离函数也可以加速。使用abs2而不是abs,并在减号上加一个点。如果你避免分配临时数组会更快。)
  • 我想我在 while 循环中重复操作。我通过放置 Matlab 版本创建了一个新问题。您可以清楚地看到 Matab 版本避免了 while 循环中的操作。链接是这样的:stackoverflow.com/questions/66937910/…
【解决方案2】:

以下应该表现得更好。最明显的区别在于它计算的F 减少了 500 倍,并且不依赖于全局变量。

function T(V,kgrid,zgrid,β,δ)
    E=V*P'
    T1 = zeros(Float64, 500, 7)
    for j = 1:500
        for i = 1:7
            x = F(zrid[i],kgrid[j]) +(1-δ)*kgrid[j] 
            T1[j,i] = maximum(u(max(x - kgrid[l], 0)) + β*E[l,i] for l in 1:500)
        end
    end
    return T1
end

【讨论】:

  • 此过程耗时 4.017568 秒。 Matlab 耗时 1.4582 秒。你认为这是因为我使用的是 Jupyter 吗?
  • 没有。这可能是uF的实现的某种组合。
  • 也可能是类型稳定性问题
  • @Fam:最大的不同是在 MATLAB 中你调用一次f,在 Julia 代码中它被调用 500x7 次。函数调用开销可能是这里的决定因素。
  • matlab 在 500x7 数组上调用该函数一次,这应该与 Julia 在单个值上被调用 500x7 次的情况大致相同。
猜你喜欢
  • 2021-06-06
  • 2014-06-17
  • 2011-07-12
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 2013-12-17
  • 1970-01-01
相关资源
最近更新 更多