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