gpt4 book ai didi

F#中懒惰的表现

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

为什么创建Lazy打字这么慢?

假设以下代码:

type T() =
let v = lazy (0.0)
member o.a = v.Value

type T2() =
member o.a = 0.0

#time "on"

for i in 0 .. 10000000 do
T() |> ignore

#time "on"

for i in 0 .. 10000000 do
T2() |> ignore

第一个循环给了我: Real: 00:00:00.647而第二个循环给了我 Real: 00:00:00.051 .懒惰慢了 13 倍!!

我试图以这种方式优化我的代码,但最终模拟代码速度慢了 6 倍。然后追踪减速发生的位置很有趣......

最佳答案

Lazy 版本有一些重要的开销代码 -

 60     .method public specialname
61 instance default float64 get_a () cil managed
62 {
63 // Method begins at RVA 0x2078
64 // Code size 14 (0xe)
65 .maxstack 3
66 IL_0000: ldarg.0
67 IL_0001: ldfld class [FSharp.Core]System.Lazy`1<float64> Test/T::v
68 IL_0006: tail.
69 IL_0008: call instance !0 class [FSharp.Core]System.Lazy`1<float64>::get_Value()
70 IL_000d: ret
71 } // end of method T::get_a

将此与直接版本进行比较
 .method public specialname
130 instance default float64 get_a () cil managed
131 {
132 // Method begins at RVA 0x20cc
133 // Code size 10 (0xa)
134 .maxstack 3
135 IL_0000: ldc.r8 0.
136 IL_0009: ret
137 } // end of method T2::get_a

所以直接版本有一个加载然后返回,而间接版本有一个加载然后调用然后返回。

lazy版本有一个额外的调用,我希望它会显着变慢。

更新:
所以我想知道我们是否可以创建一个自定义版本的 lazy这不需要方法调用 - 我还更新了测试以实际调用方法,而不仅仅是创建对象。这是代码:
type T() =
let v = lazy (0.0)
member o.a() = v.Value

type T2() =
member o.a() = 0.0

type T3() =
let mutable calculated = true
let mutable value = 0.0
member o.a() = if calculated then value else failwith "not done";;

#time "on"
let lazy_ =
for i in 0 .. 1000000 do
T().a() |> ignore
printfn "lazy"
#time "on"
let fakelazy =
for i in 0 .. 1000000 do
T3().a() |> ignore
printfn "fake lazy"

#time "on"
let direct =
for i in 0 .. 1000000 do
T2().a() |> ignore
printfn "direct";;

这给出了以下结果:
lazy
Real: 00:00:03.786, CPU: 00:00:06.443, GC gen0: 7

val lazy_ : unit = ()


--> Timing now on

fake lazy
Real: 00:00:01.627, CPU: 00:00:02.858, GC gen0: 2

val fakelazy : unit = ()


--> Timing now on

direct
Real: 00:00:01.759, CPU: 00:00:02.935, GC gen0: 2

val direct : unit = ()

这里 lazy版本仅比直接版本慢 2 倍,而假懒惰版本甚至比直接版本快一点——这可能是由于在基准测试期间发生了 GC。

关于F#中懒惰的表现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12034774/

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