Решено: Не пойму откуда такая разница во времени выполения (С++ с -О2 и без него)

Модератор: Модераторы разделов

Warlornhor
Сообщения: 428
ОС: openSUSE 12.3

Решено: Не пойму откуда такая разница во времени выполения

Сообщение Warlornhor »

Доброго времени суток.

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

Код: Выделить всё

for (int i = 0; i < 1000000000; i++) {
       double d = exp(-2);
}

Попробовал скомпилировать этот код с ключом -О2 и без него, так вот с ключом выполнение этой "программки" занимает примерно 350мс, а без ключа примерно 3-4 секунды. Пробовал то же на Java, не дождался. А теперь вопрос это что правда скорость увеличилась в 10 раз с ключом или я что-то не так сделал? Работало это все на openSUSE 11.1 x86_64, gcc из репозитория, процессор intel t2390.

И еще вопрос, если я менял тип int на int64_t, то можно было еще пару ноликов написать, а время выполнения с ключом не менялась, но увеличивалось время выполнения без ключа и доходило до отрыва в скорости примерно в 20 раз. Как такое может быть? Реально ли увеличится скорость программы если основные операции в ней --- это вычисление экспоненты, взятие значения из HashMap'а и запись новых туда же, если я перепишу ее с Java на C++?
Спасибо сказали:
ryuu
Сообщения: 14
ОС: Arch Linux

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение ryuu »

Компилятор с флагом оптимизации увидел, что данное выражение не имеет смысла и выбросил эту конструкцию, без флага, соотвественно, оставил.
World Destroyer, The
Спасибо сказали:
Warlornhor
Сообщения: 428
ОС: openSUSE 12.3

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение Warlornhor »

ryuu писал(а):
29.10.2009 10:21
Компилятор с флагом оптимизации увидел, что данное выражение не имеет смысла и выбросил эту конструкцию, без флага, соотвественно, оставил.

Интересное предположение, но если та же самая "программа" выполняется и компилируется на x86 Ubunte8.04, то время выполнения даже на более мощном процессоре E6550 занимает времени больше (около 7 секунд, если i меняется до 1 и 8 ноликов), а флаг оптимизации ни на что не влияет.
Спасибо сказали:
ryuu
Сообщения: 14
ОС: Arch Linux

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение ryuu »

Warlornhor писал(а):
29.10.2009 10:26
ryuu писал(а):
29.10.2009 10:21
Компилятор с флагом оптимизации увидел, что данное выражение не имеет смысла и выбросил эту конструкцию, без флага, соотвественно, оставил.

Интересное предположение, но если та же самая "программа" выполняется и компилируется на x86 Ubunte8.04, то время выполнения даже на более мощном процессоре E6550 занимает времени больше (около 7 секунд, если i меняется до 1 и 8 ноликов), а флаг оптимизации ни на что не влияет.

Странно...

Вот пример программы:

Код: Выделить всё

#include <stdio.h>
#include <math.h>

typedef unsigned int ui32;

int main(int argc, char **argv)
{
    ui32 i;

    for (i = 0; i < (ui32)-1; ++i)
    {
        /* printf("\r%u", i); */
        double d = exp(-2);
    }
    putchar('\n');
    return 0;
}


Результат без флага оптимизации (gcc main.c -S):

Код: Выделить всё

        .file   "main.c"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $32, %esp
        movl    $0, 20(%esp)
        jmp     .L2
.L3:
        fldl    .LC0
        fstpl   24(%esp)
        addl    $1, 20(%esp)
.L2:
        cmpl    $-1, 20(%esp)
        jne     .L3
        movl    $10, (%esp)
        call    putchar
        movl    $0, %eax
        leave
        ret
        .size   main, .-main
        .section        .rodata
        .align 8
.LC0:
        .long   -1547730484
        .long   1069634218
        .ident  "GCC: (GNU) 4.4.2"
        .section        .note.GNU-stack,"",@progbits


Результат с флагом оптимизации (gcc -O2 main.c -S):

Код: Выделить всё

        .file   "main.c"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp
        movl    stdout, %eax
        movl    $10, (%esp)
        movl    %eax, 4(%esp)
        call    _IO_putc
        xorl    %eax, %eax
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.2"
        .section        .note.GNU-stack,"",@progbits


Как видно: без флага оптимизации компилятор оставил цикл, с флагом выкинул.
World Destroyer, The
Спасибо сказали:
Warlornhor
Сообщения: 428
ОС: openSUSE 12.3

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение Warlornhor »

Еще бы я понял что это за вывод... Я пробовал выводить значение d через стандартный выход, и цикл был на месте что с ключом что без него, все равно странно если этот ключ убирает такой цикл в зависимости от архитектуры. Но, спасибо за ответ, буду думать дальше.
Спасибо сказали:
ryuu
Сообщения: 14
ОС: Arch Linux

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение ryuu »

Он и останется на месте, если в этом цикле есть что-то конструктивное, например, вывод значений.
В случае с вычислением экспоненциальной функции, где аргумент не меняется и переменная d нигде не используется, компилятор с флагом оптимизации выкинет цикл, т.к. считает, что это бессмысленная трата времени.
World Destroyer, The
Спасибо сказали:
Warlornhor
Сообщения: 428
ОС: openSUSE 12.3

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение Warlornhor »

Хм, буду дома напишу что-нибудь вроде:

Код: Выделить всё

double d;
for (int i = 0; i < 1000000000; i++) {
       d = exp(-2);
}
cout << d;

Если скорость так и останется в 10 раз различной, то я вообще ничего не понимаю.
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение RasenHerz »

Warlornhor писал(а):
29.10.2009 11:17
Хм, буду дома напишу что-нибудь вроде:

Код: Выделить всё

double d;
for (int i = 0; i < 1000000000; i++) {
       d = exp(-2);
}
cout << d;

Если скорость так и останется в 10 раз различной, то я вообще ничего не понимаю.

Ну и c включеной оптимизацией компилятор превратит это в:

Код: Выделить всё

cout << double(exp(-2));

Чтобы этого не было надо подобрать выражение в цикле так чтобы оно зависело от i
Спасибо сказали:
Аватара пользователя
Фантом
Сообщения: 460
ОС: openSUSE

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение Фантом »

А Вы уверены, что дело в архитектуре? Сравните версии gcc в двух используемых дистрибутивах. Если не ошибаюсь, в Ubuntu 8.04 входит 4.2, а в SuSE 11.1 - 4.3.
Спасибо сказали:
Warlornhor
Сообщения: 428
ОС: openSUSE 12.3

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение Warlornhor »

Мдаа, в общем вчера попробовал задействовать переменную i в вычислении и в итоге получил что скорость не изменяется, однако все же в 2 раза быстрее чем Java, что же буду думать дальше.

Спасибо за подсказку.
Спасибо сказали:
Аватара пользователя
iljaCPP
Сообщения: 48
ОС: Slackware

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение iljaCPP »

А с volatile ?
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение RasenHerz »

Warlornhor писал(а):
30.10.2009 08:53
Мдаа, в общем вчера попробовал задействовать переменную i в вычислении и в итоге получил что скорость не изменяется, однако все же в 2 раза быстрее чем Java, что же буду думать дальше.

Спасибо за подсказку.

А как задействовали? Может и там компилятор смог оптимизировать выражение. Попробуйте что-то вроде:

Код: Выделить всё

double d;
for (int i = 0; i < 1000000000; i++) {
       d += exp(-2*(i % 5));
}
cout << d;

Теперь уж точно не оптимизирует =)
Спасибо сказали:
Warlornhor
Сообщения: 428
ОС: openSUSE 12.3

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение Warlornhor »

RasenHerz писал(а):
30.10.2009 21:47

Код: Выделить всё

double d;
for (int i = 0; i < 1000000000; i++) {
       d += exp(-2*(i % 5));
}
cout << d;

Теперь уж точно не оптимизирует =)

Вот примерно так я и сделал, действительно, оптимизация в таком коде не работает.
Спасибо сказали:
JelF
Сообщения: 62
ОС: Debian

Re: Решено: Не пойму откуда такая разница во времени выполения

Сообщение JelF »

хитроумность компиляторов вызывает сомнение в том, для кого они пишутся.

gcc даже арифмеитическую прогрессию берет автоматом, Такие милые сердцу любого индуса строчки как

Код: Выделить всё

 i=1;
while(i<10000) {
    i++;
    d=i*3;
}
даже не стоят рассмотрения
Спасибо сказали: