Подтвердить что ты не робот

Умножается быстрее, чем поплавковое деление?

В C/С++ вы можете настроить следующий код:

double a, b, c;
...
c = (a + b) / 2;

Это делает то же самое, что и:

c = (a + b) * 0.5;

Мне интересно, что лучше использовать. Является ли одна операция существенно быстрее, чем другая?

4b9b3361

Ответ 1

Умножение происходит быстрее, чем деление. В университете мне учили, что разделение занимает в шесть раз больше, чем умножение. Фактические тайминги зависят от архитектуры, но в целом умножение никогда не будет медленнее или даже медленнее, чем деление. Всегда оптимизируйте свой код для использования умножения, если позволяют ошибки округления.

Итак, в примере это обычно будет медленнее...

for (int i=0; i<arraySize; i++) {
    a[i] = b[i] / x;
}

... чем это...

y=1/x;
for (int i=0; i<arraySize; i++) {
    a[i] = b[i] * y;
}

Конечно, с ошибками округления, вы потеряете (небольшую) точность во втором методе, но если вы не будете многократно вычислять x=1/x;, что вряд ли вызовет много проблем.

Edit:

Просто для справки. Я искал сравнение времени работы сторонних разработчиков, выполнив поиск в Google.

http://gmplib.org/~tege/x86-timing.pdf

Посмотрите на цифры на MUL и DIV. Это указывает на разницу в 5-10 раз в зависимости от процессора.

Ответ 2

Умножение с плавающей запятой обычно занимает меньше циклов, чем деление с плавающей запятой. Но с буквальными операндами оптимизатор хорошо осведомлен о таких микро-оптимизации.

Ответ 3

Вполне вероятно, что в этом случае компилятор преобразует разницу в умножение, если он "думает" быстрее. Разделение на 2 в плавающей запятой также может быть быстрее, чем другие поплавковые деления. Если компилятор не конвертирует его, МОЖЕТ быть быстрее использовать умножить, но не обязательно - зависит от самого процессора.

Коэффициент усиления от ручного умножения вместо деления может быть довольно большим в тех случаях, когда компилятор не может определить, что он "безопасен" для этого (например, 0,1 не может быть сохранен точно как 0,1 в числе с плавающей запятой, он становится 0.10000000149011612). Ниже приведены данные о процессорах AMD, которые можно считать репрезентативными для данного класса.

Чтобы узнать, хорошо ли ваш компилятор или нет, почему бы вам не написать немного кода для экспериментов. Убедитесь, что вы пишете его, чтобы компилятор не просто вычислил постоянное значение и отбросил все вычисления в цикле tho '.

Изменить:

Руководство по оптимизации AMD для семейных 15-х процессоров, укажите цифры для fdiv и fmul - 42 и 6 соответственно. Варианты SSE немного ближе, 24 (одиночные) или 27 (двойные) циклы для DIVPS, DIVPD DIVSS и DIVSD (деление) и 6 циклов для всех форм умножения.

Из памяти цифры Intel не так уж далеки.