Я использую основанный на журнале класс в C++ для хранения очень маленьких значений с плавающей точкой (поскольку значения иначе идут вне объема double
). Поскольку я выполняю большое количество умножения, это обладает дополнительным преимуществом преобразования умножения к суммам.
Однако в определенный момент в моем алгоритме, я должен разделить стандарт double
значение integer
значение и, чем делает a *=
к основанному на журнале значению. Я перегрузился *=
оператор для моего основанного на журнале класса и правого значения стороны сначала преобразовывается в основанное на журнале значение путем выполнения log()
и, чем добавленный к левому значению стороны. Таким образом операции, на самом деле выполненные, являются разделением с плавающей точкой, log()
и суммирование с плавающей точкой.
Мой вопрос, было ли это быстрее для первого преобразования знаменателя в основанное на журнале значение, которое заменит подразделение с плавающей точкой вычитанием с плавающей точкой, приводя к следующей цепочке операций: дважды log()
, вычитание с плавающей точкой, суммирование с плавающей точкой.
В конце это сводится к тому, быстрее ли подразделение с плавающей точкой или медленнее, чем log()
. Я подозреваю, что общий ответ был бы то, что это - компилятор и архитектурно-зависимый, таким образом, я скажу, что использую gcc 4.2 от Apple на Дарвине 10.3.0. Однако, я надеюсь получить ответ с общим комментарием по скорости этих двух операторов и/или идеи о том, как измерить различие сам, в то время как там мог бы больше продолжаться здесь, например, выполнять конструкторов, которые делают преобразование типов и т.д.
Удачи!
Вы делите одно и то же число несколько раз? Если это так, вы можете вместо этого умножить на 1./yourInteger
и выполнить деление только один раз. Если бы это было возможно, это было бы быстрее, чем любое другое.
Что касается вашего фактического вопроса, он зависит не только от компилятора и архитектуры, но и от микроархитектуры и данных.
На вашей конкретной платформе (darwin / x86) для текущего оборудования i5 / i7: ~ 24 цикла для разделения (1), ~ 35 циклов для log ()
(2). Однако, поскольку разделение использует только один слот отправки команд, аппаратный механизм переупорядочения может выполнять другие полезные вычисления, пока разделение находится в полете; log ()
, напротив, реализован программно, и поэтому у процессора меньше возможностей для выполнения других вычислений с задержкой логарифма. Это означает, что на практике деление часто происходит намного быстрее.
1) Из руководства по оптимизации Intel
2) Измерено путем вызова log ()
в узком цикле и использования mach_absolute_time ()
для получения времени стены.
Я почти уверен, что выполнение логических вычислений с помощью любого алгоритма будет намного дороже, чем даже деление FP.
Конечно, единственный способ быть уверенным - это закодировать его и измерить производительность кода. Судя по вашему описанию, не должно быть слишком сложно реализовать обе версии и попробовать их бок о бок.
В архитектуре x86 логарифмы занимают значительно больше времени, чем деления: 85 циклов (пропускная способность) для FYL2X по сравнению с 40 циклами для FDIV . Я был бы удивлен, если бы другие архитектуры сильно отличались. Используйте деление с плавающей запятой.
Основная проблема с делением заключается в том, что хотя это одна инструкция на большинстве современных CPU, она обычно имеет высокую задержку
(31 цикл на PowerPC - не уверен, что на x86). Однако часть этой задержки может быть сглажена, если у вас есть другие, не зависящие от деления инструкции, которые могут быть выполнены одновременно с делением. Так что ответ будет в некоторой степени зависеть от того, какой набор инструкций и зависимостей вы имеете в цикле, который содержит ваше деление (не говоря уже о том, какой процессор вы используете).
Учитывая это, моя интуиция подсказывает, что на большинстве архитектур деление будет быстрее, чем лог-функция.