Эффективность деления с плавающей точкой и проверки значений заранее, если экв - PullRequest
2 голосов
/ 14 января 2012

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

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

Я предполагаю, что проверка if состоит из 1 или 2 инструкций (это было некоторое время после класса ассемблера), и что операция с плавающей запятой будет намного больше, чем эта.

//Check 
if (a != 10) {              //1 or 2 instructions?
    b *= (float) a / 10;    //Many instructions?
}

Значение a в большинстве случаев будет равно 10, однако есть несколько случаев, когда этого не произойдет. Будет ли деление с плавающей точкой занимать очень много циклов, даже если a равно делителю?

Будет ли предыдущий код с оператором if выполняться эффективнее, чем просто без следующего?

//Don't check
b *= (float) a / 10;    //Many instructions?

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

Ответы [ 3 ]

5 голосов
/ 14 января 2012

Предполагая, что это какой-то невероятно трудный цикл, выполняемый миллиарды раз, поэтому разница в 1-2 инструкции имеет значение, поскольку в противном случае вам, вероятно, не стоит беспокоиться -

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

Если a == 10 всего много, я бы подумал, что есть лучший и более быстрый способ как-то воспользоваться этим, ранее в коде.

3 голосов
/ 14 января 2012

IIRC, умножение с плавающей точкой намного дешевле, чем деление, поэтому это может быть быстрее, чем оба:

b *= (a * 0.1);
1 голос
/ 14 января 2012

Если вам в конечном итоге понадобится оптимизировать этот код, я бы порекомендовал использовать Caliper для выполнения микро-тестов ваших внутренних циклов.Очень трудно точно предсказать, какой эффект будут иметь эти небольшие модификации.Особенно в Java, где поведение виртуальной машины немного неизвестно, поскольку теоретически она может оптимизировать код на лету.Лучше всего попробовать несколько стратегий и посмотреть, что работает.

http://code.google.com/p/caliper/

...