2011-05-24 2 views
3

в этом вопросе Why is this F# code so slow?, обсуждается, что структурное сравнение делает функцию let min3(a, b, c) = min a (min b c) slow; не должно ли структурное сравнение простого типа быть столь же быстрым, как и нативный? Я смущен, потому что люди говорили о том, чтобы всегда использовать HashIdentity.Structural для словаря в F # в FSharp runs my algorithm slower than Python. Если у меня есть словарь с простым типом (int или string) в качестве ключа, могу ли я получить штраф за выполнение при использовании HashIdentity.Structural?F # простой тип и структурное сравнение

ответ

3

Вообще говоря, я бы не стал беспокоиться о производительности сравнений, потому что типичные сравнения кода вряд ли будут узким местом производительности. Если вы определили, что у вас проблемы с производительностью, и профилирование показывает, что причиной являются сравнения, тогда вы можете подумать о том, как лучше всего это решить.

Если вам нужно учитывать эффективность сравнений, вам может потребоваться понять, как работает компилятор. В первом примере, который вы указали, функция 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() реализации на клавишах (что словарь будет делать по умолчанию) будет быстрее, чем при использовании структурного сравнения. Однако, будет ли это существенным отличием для вас, будет зависеть от фактического кода, который вы пишете - как я уже говорил ранее, для ключевых сравнений довольно редко приходится занимать значительную часть времени работы алгоритма.

Смежные вопросы