gpt4 book ai didi

generics - Seq.iter 比 native 映射慢 : any generic solution?

转载 作者:行者123 更新时间:2023-12-02 19:42:07 25 4
gpt4 key购买 nike

这个问题之前已经出现过,其原因由 John Palmer 回答: why is Seq.iter and Seq.map so much slower?

let ar = Array.zeroCreate<int> (64*1024*1024)
#time
//Real: 00:00:00.171, CPU: 00:00:00.171, GC gen0: 0, gen1: 0, gen2: 0
for i in 0 .. ar.Length - 1 do
ar.[i] <- ar.[i]*3

//Real: 00:00:00.327, CPU: 00:00:00.328, GC gen0: 0, gen1: 0, gen2: 0
ar |> Array.iteri(fun i _ -> ar.[i] <- ar.[i]*3)

//Real: 00:00:02.249, CPU: 00:00:02.250, GC gen0: 0, gen1: 0, gen2: 0
ar |> Seq.iteri(fun i _ -> ar.[i] <- ar.[i]*3)

我想知道是否有某种“内联”或其他通用机制可以将序列映射到(其最后已知的?)具体类型以加速这些行为。例如,这里我有静态保证,我将迭代一个数组。

您知道理论上存在对此问题满意的解决方案吗? (会有什么奇特的名字?)

是否有一些语言可以很好地承认并解决该问题?

最佳答案

确实,F# 中没有更高种类的类型,但您仍然可以使用内联函数并模拟一些 Typeclass 行为。通过定义 Functor,您可以获得 native 映射的通用解决方案:

type Fmap = Fmap with
static member ($) (_Functor:Fmap, x:List<_> ) = fun f -> List.map f x
static member ($) (_Functor:Fmap, x:array<_>) = fun f -> Array.map f x
static member ($) (_Functor:Fmap, x:_ [,] ) = fun f -> Array2D.map f x
static member ($) (_Functor:Fmap, x:_ [,,] ) = fun f -> Array3D.map f x
static member ($) (_Functor:Fmap, x:_ [,,,] ) = fun f ->
Array4D.init (x.GetLength 0) (x.GetLength 1) (x.GetLength 2) (x.GetLength 3) (fun a b c d -> f x.[a,b,c,d])

let inline fmap f x = (Fmap $ x) f

以 fmap 为例,该函数是内联函数,它将接受重载中定义的任何类型,并且执行速度与直接调用该函数一样快(这就是幕后实际发生的情况)。要进行迭代,您可以使用 fmap 并丢弃结果,在您的情况下,您可能需要定义类似 fmapi 的内容以获得可用的索引。

请记住,您应该始终使用具体类型调用这些函数,如果您传递 Seq<'a> 它将失败,您不应该混合使用两种方法:子类型和临时多态性。

关于generics - Seq.iter 比 native 映射慢 : any generic solution?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13604316/

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