Двойное умножение независимо от длины переменной? - PullRequest
2 голосов
/ 01 марта 2012

Мне было интересно, если длина двойной переменной влияет на время умножения . В целях тестирования я написал следующий небольшой фрагмент кода:

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

int main() {
    double x = 123.456;
    double a = 1.23456;
    double b = 1.234;
    double d = 1.0;

    // experiment 1
    clock_t start = clock();
    for( unsigned long long int i = 0; i < 10000000; ++i ) {
        x *= a;
    }
    clock_t end = clock();
    std::cout << "123.456*1.23456 takes " << (double)(end-start)/CLOCKS_PER_SEC << " secs" << std::endl;

    // experiment 2
    start = clock();
    for( unsigned long long int i = 0; i < 10000000; ++i ) {
        x *= b;
    }
    end = clock();
    std::cout << "123.456*1.234 takes " << (double)(end-start)/CLOCKS_PER_SEC << " secs" << std::endl;

    // experiment 3
    start = clock();
    for( unsigned long long int i = 0; i < 10000000; ++i ) {
        x *= d;
    }
    end = clock();
    std::cout << "123.456*1.0 takes " << (double)(end-start)/CLOCKS_PER_SEC << " secs" << std::endl;

    return 0;
}

Я скомпилировал его, используя VS2008, 64 бита в режиме выпуска, без оптимизации и отладочной информации . Результат неудивителен: все три вида умножения выполняются в одно и то же время с разницей всего в несколько миллисекунд. Мой вопрос: почему это так? Если я сделаю ошибку и умножу число на 1,0 вместо 1 и не использую оптимизацию компилятора, то мое умножение будет длиться намного дольше, чем умножение числа на 1! Когда люди умножаются, то чем короче число, тем быстрее мы приходим к результату. Как компьютер умножается так, что не имеет значения, как долго эти два числа?

Кроме того, я решил проверить, влияет ли отладка на скорость выполнения. В этом случае это не так: при компиляции с параметром \DEBUG или без него умножение всегда занимает одинаковое количество времени.

При включенной оптимизации \O2 такое же умножение длится всего одну тысячную секунды. Что делает оптимизация в этом случае? Как оптимизировать такой компактный код умножения двух двойных чисел в C ++?

Буду благодарен за любое объяснение, что происходит при двойном умножении в C ++ .

Ответы [ 4 ]

2 голосов
/ 01 марта 2012

Плавания (одинарная точность) - 32 бита, а удвоения - 64 бита.

http://en.wikipedia.org/wiki/IEEE_754-2008

На процессоре Intel / AMD ... FPU (x87) или SIMDD (SSEx) будет вычислять MULtiplication за постоянное количество циклов. Скорость основана на пропускной способности, базовых операциях и задержке.

http://www.agner.org/optimize/instruction_tables.pdf

  • FMUL - Умножение FPU x87
  • MULSS - многократный скалярный одиночный SSEx
  • MULDS - умноженный скалярный двойной SSEx
2 голосов
/ 01 марта 2012

Переменные всегда имеют одинаковую длину, но значения отличаются.Другими словами: операции, выполняемые на аппаратном уровне, одинаковы, что приводит к получению.Например, целое число, умноженное на 0 (результат обнуления, т.е. передача 0 в регистр назначения), занимает то же время, что и умножение на 1 (копирование операнда в регистр назначения).

1 голос
/ 02 марта 2012

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

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

1 голос
/ 01 марта 2012

При включенной оптимизации \ O2 такое же умножение длится всего одну тысячную секунды. Что делает оптимизация в этом случае?

Так как вы никогда не используете свой результат (x), полностью допустимо исключить все умножения. Попробуйте отобразить результаты.

Также обратите внимание, что вы выполняете умножения 10M, с современным процессором у вас есть по крайней мере 1G тактов в секунду, и в этом случае он выполняет очень узкий цикл.

...