Как я могу сравнить производительность деления 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( ) чтобы получить время стены.

В архитектуре x86 логарифмы занимают значительно больше времени, чем деления: 85 циклов (пропускная способность) для FYL2X по сравнению с 40 циклами для FDIV. Я был бы удивлен, если бы другие архитектуры сильно отличались. Перейти с делением с плавающей точкой.

Основная проблема с разделением заключается в том, что, хотя на большинстве современных процессоров это одна инструкция, она обычно имеет высокую latency (31 цикл на PowerPC - не уверен, что на x86). Некоторые из этих задержек могут быть скрыты, если у вас есть другие независимые инструкции, которые могут быть изданы одновременно с делением. Таким образом, ответ будет зависеть в некоторой степени от того, какой набор команд и зависимости у вас есть в цикле, который содержит ваш разрыв (не говоря уже о том, какой процессор вы используете).

Сказав это, я чувствую, что разделение будет быстрее, чем функция журнала на большинстве архитектур.

Я уверен, что вычисление лога с использованием любого алгоритма будет обходиться дороже, чем даже деление FP.

Конечно, единственный способ убедиться в этом - это написать код и измерить производительность кода. Из вашего описания звучит так, как будто не должно быть слишком сложно реализовать обе версии и попробовать их параллельно.

Другие вопросы по тегам