gpt4 book ai didi

f# - 有人知道 QuotationEvaluator 这么慢的原因吗?

转载 作者:行者123 更新时间:2023-12-01 03:54:44 26 4
gpt4 key购买 nike

F# 社区的常识是,PowerPack 的引用编译工具生成的代码非常慢,事实上它的执行速度甚至比幼稚的解释还要糟糕。我一直在研究造成这种情况的原因,但到目前为止我还没有找到令人信服的答案。有人声称,这种情况的发生要么是因为引用中的模式匹配等事物的低效表示,要么是因为库使用的表达式树固有的低效。我想用一个简单的例子来说明为什么我认为两者都不正确:


#r "FSharp.Powerpack.Linq.dll"

open System
open System.Linq.Expressions

open Microsoft.FSharp.Quotations.Patterns

let powerpack = Microsoft.FSharp.Linq.QuotationEvaluator.Compile <@ 1 + 1 @>

// explicitly rewrite above quotation with expression trees
let expressionTree =
let (Call(_,addM,_)) = <@ 1 + 1 @>
let constExpr (x : 'T) = Expression.Constant(box x, typeof<'T>)
let eval = Expression.Call(addM, constExpr 1, constExpr 1)
let lambda = Expression.Lambda<Func<int>>(eval)
lambda.Compile()

// reflection - based evaluation
let reflection =
let (Call(_,addM,_)) = <@ 1 + 1 @>
fun () -> addM.Invoke(null, [| 1 :> obj ; 1 :> obj |]) :?> int

#time

// QuotationEvaluator ~ 2.5 secs
for i in 1 .. 1000000 do
powerpack () |> ignore

// native evaluation ~ 1 msec
for i in 1 .. 1000000 do
(fun () -> 1 + 1) () |> ignore

// reflection evaluation ~ 700 msec
for i in 1 .. 1000000 do
reflection () |> ignore

// naive expression tree ~ 19 msec
for i in 1 .. 1000000 do
expressionTree.Invoke () |> ignore

这里显然出了问题。问题是,什么?

编辑: FSharpx.Linq 编译器也会发生相同的行为

最佳答案

下面是编译的实现:

let CompileImpl (e: #Expr, eraseEquality) = 
let ty = e.Type
let e = Expr.NewDelegate(GetFuncType([|typeof<unit>; ty |]), [new Var("unit",typeof<unit>)],e)
let linqExpr = Conv (e,eraseEquality)
let linqExpr = (linqExpr :?> LambdaExpression)
let d = linqExpr.Compile()
(fun () ->
try
d.DynamicInvoke [| box () |]
with :? System.Reflection.TargetInvocationException as exn ->
raise exn.InnerException)

注意 DynamicInvoke 的使用在委托(delegate)上,比 Invoke 慢得多以及你得到结果的原因。

关于f# - 有人知道 QuotationEvaluator 这么慢的原因吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18298691/

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