我一直在寻找一种方法来使用.NET进行适当的算法编码,同时具有现代语言的所有优点(例如,我喜欢强类型检查、运算符重载、lambda、泛型算法)。通常我用C++编写我的算法(主要是图像处理)。由于F#作为一种语言似乎很有趣,我玩了一点,但它似乎非常慢。作为一个最简单的测试,我只是做了一些数组操作,增加了图像的->亮度:
let r1 = rgbPixels |> Array.map (fun x -> x + byte(10) )它似乎比比较的C++实现慢至少8倍-对于更复杂的算法,如2D卷积,情况更糟。有没有更快的方法,或者我错过了任何特定的编译器设置(是的,构建带有优化的版本...)?我愿意为好的和高的抽象买单,但是这样的开销是不好的(我需要在8个内核上并行来补偿:) --至少它破坏了进一步学习的动力……我的另一个选择是将较重的算法留在C++中,并与管理的C++接口,但这并不好,因为维护托管包装器将是一个相当大的负担。
发布于 2012-02-08 05:02:08
如果您担心性能,那么需要记住的重要一点是,F#在默认情况下不会发生任何变化。这需要在许多简单的算法实现中进行复制,例如您描述的算法。
编辑:我不知道为什么,但是对以下代码的简单测试提供的结果不如Array.map。在执行这些类型的优化时,请确保分析您尝试的任何算法。然而,我在for和map之间得到了非常相似的结果。
Array.map会为操作结果创建一个新数组,而您需要的是Array.iteri。
rgbPixels |> Array.iteri (fun i x -> rgbPixels.[i] <- x + 10uy)请注意,这可以封装在您自己的模块中,如下所示
module ArrayM =
let map f a = a |> Array.iteri (fun i x -> a.[i] <- f x)不幸的是,这是一个必要的错误,因为函数式编程的主要租用者之一是在算法允许的情况下尽可能地坚持不可变对象,然后一旦完成,在性能至关重要的地方更改为突变。如果你知道你的性能从一开始就很关键,你就需要从这些帮助器开始。
还要注意的是,可能有一个库提供了这种功能,我只是不知道它在手边。
发布于 2012-02-08 05:18:15
我认为可以肯定地说,对于数组操作,惯用的F#通常无法与优化的C++的性能相匹配,原因有几个:
将根据.NET中的数组边界检查
fun i -> ...)等抽象相比,F#通常会有少量的开销。在紧密循环中,与在循环体中完成的工作相比,这个小的开销可能会非常重要。在账本的另一边,
https://stackoverflow.com/questions/9183646
复制相似问题