You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带Type参数的多分派函数与普通函数性能是否相当?

带::Type{Algo1}参数的多分派函数调用是否与普通函数执行速度相当?

注意: 答案并非如此简单,请查看下方更新内容

我希望使用多分派版本来优化代码结构,但担心其执行速度会变慢?

普通版本

algo1_Init() = 0.0
@inline algo1_update(state) = state + 1.0 # should be very fast

fit1(Init, update) = begin
  state = Init()
  for _ in 1:1e6
    state = update(state) # very heavy loop
  end
  state
end

fit1(algo1_Init, algo1_update)

多分派版本

struct Algo1 end
Init(::Type{Algo1}) = 0.0
@inline update(::Type{Algo1}, state) = state + 1.0 # should be very fast

fit2(T) = begin
  state = Init(T)
  for _ in 1:1e6
    state = update(T, state) # very heavy loop
  end
  state
end

fit2(Algo1)

更新内容

测试结果显示二者性能并非始终一致,多分派版本的速度约为普通版本的1/1.5。此外还有两个意外的无关发现:

  • a) 数组中的missing值会使计算速度降低10倍,详见代码中的CHANGE2;
  • b) 返回两个值比返回一个值慢10倍,详见代码中的CHANGE1。

基准测试代码

using Distributions, BenchmarkTools

struct SimpleVol end

@inline predict(::Type{SimpleVol}, Q, prev, r) = begin
  d = r - Q.μ
  y = sqrt(d*d + 1e-6)

  v = Q.α*y + (1-Q.α)*prev.v

  (; v), 0.0
  # (; v) # CHANGE1
end

@inline predict_explicit(Q, prev, r) = begin
  d = r - Q.μ
  y = sqrt(d*d + 1e-6)

  v = Q.α*y + (1-Q.α)*prev.v

  (; v), 0.0
  # (; v) # CHANGE1
end

vol_llh_multi(T, Q, rs) = begin
  n = length(rs)
  l = findfirst(!ismissing, rs)
  state = (; v=abs(rs[l]))
  for t in max(l, 2):n
    rs[t] === missing && continue
    state, _ = predict(T, Q, state, rs[t])
    # state = predict(T, Q, state, rs[t]) # CHANGE1
  end
end;

vol_llh_explicit(T, Q, rs) = begin
  n = length(rs)
  l = findfirst(!ismissing, rs)
  state = (; v=abs(rs[l]))
  for t in max(l, 2):n
    rs[t] === missing && continue
    state, _ = predict_explicit(Q, state, rs[l])
    # state = predict_explicit(Q, state, rs[l]) # CHANGE1
  end
end;

returns = rand(Normal(0, 0.015), 10_000);

isweekend(i) = (mod(i,7) == 6) || (mod(i,7) == 0);
returns2 = [isweekend(i) ? missing : returns[i] for i in 1:length(returns)];

# Warmup
vol_llh_explicit(SimpleVol, (α = 0.048, μ = 0.0004, ν = 4.203), returns2)
vol_llh_multi(SimpleVol, (α = 0.048, μ = 0.0004, ν = 4.203), returns2)

# Bench
println("Explicit Method")
@benchmark vol_llh_explicit(SimpleVol, (α = 0.048, μ = 0.0004, ν = 4.203), returns2)
println("Multi Method")
@benchmark vol_llh_multi(SimpleVol, (α = 0.048, μ = 0.0004, ν = 4.203), returns2)

# CHANGE2 use returns instead of returns2 in benchmark

内容的提问来源于stack exchange,提问作者Alex Craft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 05:14:50