F # простой тип и структурное сравнение - PullRequest
3 голосов
/ 24 мая 2011

в этом вопросе Почему этот код F # такой медленный? , обсуждается, что структурное сравнение делает функцию let min3(a, b, c) = min a (min b c) медленной; Разве структурное сравнение простого типа не должно быть таким же быстрым, как у нативного? Я запутался, потому что люди говорили о том, что всегда использовать HashIdentity.Structural для словаря в F # в FSharp работает мой алгоритм медленнее, чем Python . Если у меня есть словарь с простым типом (int или string) в качестве ключа, получу ли я снижение производительности за использование HashIdentity.Structural?

1 Ответ

3 голосов
/ 24 мая 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...