LINUX.ORG.RU

Баг g++? Или ...


0

0

Приветствую. Я пытался немного оптимизировать сравнение знаков у двух переменных типа double. Вот что получилось:

#include <iostream>

using namespace std;

inline bool sign(double x){return !((*(((unsigned int*)&(x)) + 1))&0x80000000);}
inline bool sign1(double x){return (x>=0.0);}

inline bool cmp(double x,double y){
return ((*(((unsigned int*)&(x)) + 1))&0x80000000)^((*(((unsigned int*)&(y)) + 1))&0x80000000);
}

inline bool cmp1(double x,double y){
return ((x>=0.0)!=(y>=0.0));
}

int main(void){
double a(1.0),b(1.0);

cout << sign(a) << " " << sign(b) << " " << sign1(a) << " " << sign1(b) << endl;
cout << cmp(a,b) << " " << cmp1(a,b) << endl;
cout << a << " " << b << endl;
}

Проблема в том, что программа не правильно работает с оптимизацией -O2 и -O3.

Для gcc 3.4.3 я получаю:

g++-3.4 gcc_bug2.cpp -O2;./a.out
0 1 1 1
1 0
1 1

gcc 3.3.2 20031216 (prerelease) (SuSE Linux):

g++ gcc_bug2.cpp -O3;./a.out
1 1 1 1
1 0
1 1

Правильный ответ должен быть:
1 1 1 1
0 0
1 1

Без оптимизции и на интеловском компиляторе все работает правильно.

А с -O1?

Вот флаги O2. Определи, какой из них может воду намутить:
        <!-- O2 options -->
        <flag type="simple" value="-foptimize-sibling-calls" />     
        <flag type="simple" value="-fcse-follow-jumps" />           
        <flag type="simple" value="-fcse-skip-blocks" />            
        <flag type="simple" value="-fgcse" />                       
        <flag type="simple" value="-fexpensive-optimizations" />    
        <flag type="simple" value="-fstrength-reduce" />            
        <flag type="simple" value="-frerun-cse-after-loop" />       
        <flag type="simple" value="-frerun-loop-opt" />             
        <flag type="simple" value="-fcaller-saves" />               
        <flag type="simple" value="-fforce-mem" />                  
        <flag type="simple" value="-fpeephole2" />                  
        <flag type="simple" value="-fschedule-insns" />             
        <flag type="simple" value="-fschedule-insns2" />            
        <flag type="simple" value="-fregmove" />                    
        <flag type="simple" value="-fstrict-aliasing" />            
        <flag type="simple" value="-fdelete-null-pointer-checks" /> 
        <flag type="simple" value="-freorder-blocks" /> 

        <!-- O2 options for GCC 3.3 -->
        <flag type="simple" value="-fsched-interblock" />           
        <flag type="simple" value="-fsched-spec" />                 
        <flag type="simple" value="-freorder-functions" />          
        <flag type="simple" value="-falign-loops" />                
        <flag type="simple" value="-falign-jumps" />                
        <flag type="simple" value="-falign-labels" />               

        <!-- O2 options for GCC 3.4 -->
        <flag type="simple" value="-funit-at-a-time" />             
        <flag type="simple" value="-falign-functions" /

Selecter ★★★★
()
Ответ на: комментарий от Selecter

Хотя я уже проверил каждый флаг по отдельности с -O1. Значит при определённой комбинации получается такая бага.

Selecter ★★★★
()
Ответ на: комментарий от Selecter

Причём :)

$ g++ -O2  -o test test.cpp && ./test
0 0 1 1
0 0
1 1

gcc version 3.4.3-20050110 (Gentoo Linux 3.4.3.20050110-r1, ssp-3.4.3.20050110-0, pie-8.7.7)

Selecter ★★★★
()
Ответ на: комментарий от Selecter

Опередил ;). Я тоже этот флаг нашел и все заработало даже на O3. Сейчас попробую отправит в их багзиллу багрепорт.

Evgeny_I
() автор топика
Ответ на: комментарий от Evgeny_I

И, кстати, что за задача такая, что ускорение сравнения знаков пусть даже в полтора раза даст существенный выигрышь в сумме? Я вот в упор ничего подобного придумать не могу. Расскажи уж, а то у меня крыша съедет!!!

WidowMaker
()
Ответ на: комментарий от WidowMaker

>что за задача такая
Поиск корней уравнения методом деления отрезка пополам. Подсчет кол-ва пересечений координатных осей графиком.

>существенный выигрышь
На существенный выигрыш я не надеялся, просто прочитал на одном форуме, что так можно сделать и решил попробовать.

Evgeny_I
() автор топика
Ответ на: комментарий от Evgeny_I

Рекомендую хороший инструмент - профайлер. Посмотри, сколько процентов времени твой алгоритм проводит в сравении знаков. Интересу ради посчитай, на сколько процентов быстрее он заработает, если ускоришь сравнение знаков в 100 раз (что невозможно, конечно же). После подобных экзерсисов на всю жизнь пропадёт желание заниматься бесполезной оптимизацией. Оптимизировать надо только bottleneck-и!!!

WidowMaker
()

кстати твоя ф-ция отличается от обычного сравнения только поведением на нанах. То есть gcc -ffast-math по идее должен быть способен генерировать быстрые сравнения..

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> на нанах

специально для новеньких модераторов замечу что это не нецензурное выражение..

dilmah ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.