Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как заставить компилятор VC оптимизировать деление 
V
    Опции темы
borisbn
Дата 24.7.2010, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Добрый currentTime() smile
Столкнулся с такой проблемой: не могу заставить компилятор MSVC 2008 оптимизировать следующий код:
Код

double a[ 80000 ];
for ( int i = 0; i < 80000; i++ ) {
    a[ i ] = rand() % 80000;
}
TimeMeasure t;
double x = 0;
double k = 1.0 / 3.0;
for ( int i = 0; i < 80000; i++ ) {
    x += a[ i ] / 3;
    // x += y * k;
}
printf( "x = %.6f tm = %.2f", x, t.elapsed_mks() );

Конфигурация: Release, опция оптимизации: Maximize Speed (/O2)
При операции деления получаю:
Цитата

x = 438237675.666662 tm = 1100.70
x = 438237675.666662 tm = 1098.79
x = 438237675.666662 tm = 1104.92

заменяю руками деление на 3 умножением на 1/3, получаю:
Цитата

x = 438237675.666662 tm = 150.18
x = 438237675.666662 tm = 154.01
x = 438237675.666662 tm = 152.48

Может, конечно, он и не должен этого делать сам, но я, почему-то, считал, что должен...

P.S. Неужели до сих пор операция деления в процессоре ( у меня Core i7 ) выполняется дольше умножения ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Abyx
Дата 24.7.2010, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



x * (1.0 / y)  != x / y
по этому компилятор их не заменяет.
он не знает какая вам нужна точность вычислений.
заменяйте руками, там где надо

Добавлено через 1 минуту и 42 секунды
и да, деление по определению медленнее умножения - там другая сложность
PM MAIL   Вверх
borisbn
Дата 24.7.2010, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Abyx, спасибо! Действительно, как-то сразу не сообразил, что для процессора ( не для математики ) x * (1.0 / y)  != x / y
а то, что деление сложнее умножения я, конечно, знаю. Я просто думал, что процессор, с его конвеерами, различные операции подготавливает за разное время, а выполняет практически все - за одно. Получается - ошибался.
Закрываю.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
VictorTsaregorodtsev
Дата 24.7.2010, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 28.7.2006

Репутация: 1
Всего: 8



borisbn, кстати, всё равно чуть-чуть не сходится ;)
Смотрю для Корки7 растактовку команд в мануале от Агнера Фога - там для умножения латентность 5, для деления - 7-27 (и оба они, и умножение, и деление, выполняются за одну микрооперацию). Т.е. макс.задержка 27/5~~5.5 меньше, чем имеющееся у Вас соотношение 1100/150~~7.3. Поэтому если шарите в ассемблере, гляньте на сгенерированный ассемблерный код - может, компилятор еще где-по мелочи гадит.

Ну а самый быстрый вариант - выносить умножение (или деление) на константу вообще ВНЕ ЦИКЛА smile
PM MAIL WWW   Вверх
borisbn
Дата 24.7.2010, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



VictorTsaregorodtsev, посмотрел: ничего "военного". Он просто развернул этот цикл в 10 раз и вызывает себе fdiv или fmul соответственно.
Деление
Цитата

; 31   :     double k = 1.0 / 30000.0;
; 32   :     for ( int i = 0; i < 80000; i++ )

    fld    QWORD PTR __real@40dd4c0000000000
    xor    eax, eax
$LN3@main:

; 33   :     {
; 34   :      x += a[ i ] / 30000;

    fld    QWORD PTR _a$[esp+eax*8+640064]
    add    eax, 10     ; 0000000aH
    cmp    eax, 80000    ; 00013880H
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+639992]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640000]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640008]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640016]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640024]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640032]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640040]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640048]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640056]
    fdiv    ST(0), ST(1)
    faddp    ST(2), ST(0)
    jl    SHORT $LN3@main


Умножение
Цитата

; 31   :     double k = 1.0 / 30000.0;
; 32   :     for ( int i = 0; i < 80000; i++ )

    fld    QWORD PTR __real@3f0179ec9cbd821e
    xor    eax, eax
$LN3@main:

; 33   :     {
; 34   :      //x += a[ i ] / 30000;
; 35   :      x += a[ i ] * k;

    fld    QWORD PTR _a$[esp+eax*8+640064]
    add    eax, 10     ; 0000000aH
    cmp    eax, 80000    ; 00013880H
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+639992]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640000]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640008]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640016]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640024]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640032]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640040]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640048]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    fld    QWORD PTR _a$[esp+eax*8+640056]
    fmul    ST(0), ST(1)
    faddp    ST(2), ST(0)
    jl    SHORT $LN3@main



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Abyx
Дата 24.7.2010, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



VictorTsaregorodtsev, вы наверное про imul\idiv читали, а не про fmul\fdiv
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0449 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.