Плавающая точка против целочисленных вычислений на современном оборудовании - PullRequest
95 голосов
/ 31 марта 2010

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

Теперь я помню, как читал о том, как вычисления с плавающей запятой были настолько медленными примерно за 386 дней, где, как я полагаю (IIRC), был дополнительный сопроцессор. Но, конечно, в наше время с экспоненциально более сложными и мощными процессорами не имеет значения в «скорости», если выполнять вычисления с плавающей запятой или целочисленные? Тем более что фактическое время вычислений ничтожно по сравнению с чем-то вроде вызова останова конвейера или извлечения чего-либо из основной памяти?

Я знаю, что правильный ответ - это тестирование на целевом оборудовании, что будет хорошим способом проверить это? Я написал две крошечные программы на C ++ и сравнил их время выполнения с «временем» в Linux, но фактическое время выполнения слишком изменчиво (не помогает мне работать на виртуальном сервере). Если не считать того, что я провел весь день, выполняя сотни тестов, составляя графики и т. Д., Могу ли я что-то сделать, чтобы получить разумную проверку относительной скорости? Есть идеи или мысли? Я совершенно не прав?

Программы, которые я использовал следующим образом, ни в коем случае не идентичны:

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <time.h>

int main( int argc, char** argv )
{
    int accum = 0;

    srand( time( NULL ) );

    for( unsigned int i = 0; i < 100000000; ++i )
    {
        accum += rand( ) % 365;
    }
    std::cout << accum << std::endl;

    return 0;
}

Программа 2:

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <time.h>

int main( int argc, char** argv )
{

    float accum = 0;
    srand( time( NULL ) );

    for( unsigned int i = 0; i < 100000000; ++i )
    {
        accum += (float)( rand( ) % 365 );
    }
    std::cout << accum << std::endl;

    return 0;
}

Заранее спасибо!

Редактировать: Платформа, о которой я забочусь, - это обычные x86 или x86-64, работающие на настольных компьютерах с Linux и Windows.

Редактировать 2 (вставлено из комментария ниже): В настоящее время у нас обширная база кода. На самом деле я столкнулся с обобщением, что мы «не должны использовать float, поскольку целочисленные вычисления быстрее» - и я ищу способ (если это даже верно) опровергнуть это обобщенное предположение. Я понимаю, что было бы невозможно предсказать точный результат для нас, если бы мы не выполнили всю работу и не профилировали ее впоследствии.

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

Ответы [ 11 ]

0 голосов
/ 31 марта 2010

Основываясь на этом "о чем-то надежном" чем-то, что я слышал ", в прежние времена целочисленные вычисления были примерно в 20-50 раз быстрее, чем с плавающей запятой, и в наши дни они менее чем в два раза быстрее.

...