【问题标题】:F# simple type and structural comparisonF#简单类型和结构比较
【发布时间】:2011-08-31 22:21:44
【问题描述】:

在这个问题Why is this F# code so slow?中,讨论了结构比较使函数let min3(a, b, c) = min a (min b c) 变慢;简单类型的结构比较不应该和原生类型一样快吗? 我很困惑,因为人们谈论总是在FSharp runs my algorithm slower than Python 中使用HashIdentity.Structural 作为 F# 中的字典。如果我有一个以简单类型(int 或 string)为键的字典,我是否会因使用 HashIdentity.Structural 而受到性能损失?

【问题讨论】:

    标签: .net f#


    【解决方案1】:

    一般来说,我不会担心比较的性能,因为对于典型的代码比较不太可能成为性能瓶颈。如果您确定存在性能问题并且分析表明比较是原因,那么您可以考虑如何最好地解决它。

    如果您确实需要考虑比较的性能,那么您可能需要了解编译器的工作原理。在您引用的第一个示例中,min3 函数的类型为 'a * 'a * 'a -> 'a when 'a : comparison。这个函数将被编译为一个 .NET 方法,它带有 3 个泛型类型的参数,在 C# 中看起来像这样:

    using LP = Microsoft.FSharp.Core.LanguagePrimitives;
    
    T min3<T>(T a, T b, T c) {
        T d = LP.HashCompare.GenericLessThanIntrinsic(b,c) ? b : c;
        return LP.HashCompare.GenericLessThanIntrinsic(d,a) ? d : a;
    }
    

    GenericLessThanIntrinsic 方法也是通用的,其中必须有逻辑来根据被比较的实际类型执行比较。这可能需要一些类型测试和虚拟方法调用。这些不是非常昂贵的操作,但它们比执行两个整数值的直接比较要慢得多。因此,如果比较占您工作量的很大一部分,则使用通用比较例程可能会对您的整体性能产生很大影响,并且将 min3 函数专门用于仅处理整数而不是任何通用值可能会很大性能取胜。

    同样,如果您只是将整数存储为字典键,那么在键上使用内置的 GetHashCode()Equals() 实现(这是字典默认执行的操作)将比使用结构比较更快。但是,这对您来说是否会产生重要差异将取决于您正在编写的实际代码 - 正如我之前所说,关键比较占用算法运行时间的很大一部分是不寻常的。

    【讨论】:

      猜你喜欢
      • 2011-04-27
      • 2015-01-08
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多