+36
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
#include <iostream>
#include <cmath>
struct Point3D
{
float x,y,z;
Point3D () {}
Point3D (float x, float y, float z) : x(x), y(y), z(z) {}
Point3D& operator -= (const Point3D& p) { x-=p.x; y-=p.y; z-=p.z; return *this; }
Point3D operator - (const Point3D& p) const { Point3D p2(*this); return (p2-=p); }
Point3D& operator *= (const float f) { x*=f; y*=f; z*=f; return *this; }
Point3D operator * (const float f) const { Point3D p2(*this); return (p2*=f); }
};
float Dot (const Point3D& p1, const Point3D& p2) { return p1.x*p2.x + p1.y*p2.y + p1.z*p2.z; }
struct Face
{
Point3D n;
float nc;
float Dist (const Point3D& p) const { return Dot(p,n)-nc; }
};
int show_float(float src)
{
union
{
int i;
float f;
} u;
u.f = src;
return u.i;
}
float from_int(int src)
{
union
{
int i;
float f;
} u;
u.i = src;
return u.f;
}
template<typename T>
T& operator<<(T& str, const Point3D& p)
{
str << std::hex << "Point3D(from_int(0x" << show_float(p.x) << "), from_int(0x" << show_float(p.y) << "), from_int(0x" << show_float(p.z) << "))";
return str;
}
struct SPoint
{
Point3D p;
bool DoCorrectFace(const Face& face)
{
bool correct = true;
float j=1.0f;
Point3D np=p;
for (;;)
{
float ad = face.Dist(np);
if (ad<=0.0f)
break;
correct=false;
np = p - (face.n*(ad*j));
j += 1.0f;
}
p=np;
return correct;
}
};
using namespace std;
int main()
{
cout << "Hello World!" << endl;
SPoint spoint;
spoint.p = Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0));
cout << "Initial p:" << endl;
cout << spoint.p << endl;
cout << "Corrected:" << endl;
Face f;
f.n = Point3D(from_int(0x3d6cc83b), from_int(0x3f0e8841), from_int(0x3f5422bd));
f.nc = from_int(0x41bac3dc);
bool result = spoint.DoCorrectFace(f);
cout << spoint.p << endl;
cout << "Done: " << result << endl;
return 0;
}
говно в gcc
g++ (rev5, Built by MinGW-W64 project) 4.8.1
вывод в -O2 -DNDEBUG :
Hello World!
Initial p:
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0))
Corrected:
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d1))
Done: 0
вывод в -O3 -DNDEBUG:
Hello World!
Initial p:
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0))
Corrected:
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0))
Done: 0
внимание вопрос: может ли быть такое, что DoCorrectFace не изменил точку ни на бит, но вернул false? В gcc может!
Запостил: TarasB,
23 Февраля 2014
TarasB 23.02.2014 14:42 # −2
-O2 -DNDEBUG и -O3 -DNDEBUG одинаково выдают хуйню (точка не изменилась после вызова), правильно точка обрабатывается вообще без -O
Konardo 23.02.2014 14:49 # −17
xyilka 23.02.2014 17:07 # −12
xyilka 23.02.2014 17:09 # −12
xyilka 23.02.2014 17:11 # −12
xyilka 23.02.2014 17:12 # −12
xyilka 23.02.2014 17:13 # −12
xyilka 23.02.2014 17:15 # −12
xyilka 23.02.2014 17:16 # −12
xyilka 23.02.2014 17:16 # −12
Stertor 23.02.2014 17:17 # −4
xyilka 23.02.2014 17:17 # −12
xyilka 23.02.2014 17:18 # −12
xyilka 23.02.2014 17:19 # −12
xyilka 23.02.2014 17:20 # −12
xyilka 23.02.2014 17:20 # −13
Stertor 23.02.2014 17:21 # −10
xyilka 23.02.2014 17:21 # −13
xyilka 23.02.2014 17:22 # −14
xyilka 23.02.2014 17:23 # −14
xyilka 23.02.2014 17:25 # −14
anonimb84a2f6fd141 23.02.2014 19:16 # −4
anonimb84a2f6fd141 23.02.2014 19:16 # −4
anonimb84a2f6fd141 23.02.2014 19:18 # −4
anonimb84a2f6fd141 23.02.2014 19:21 # −4
anonimb84a2f6fd141 23.02.2014 19:21 # −4
anonimb84a2f6fd141 23.02.2014 19:22 # −4
anonimb84a2f6fd141 23.02.2014 19:24 # −4
anonimb84a2f6fd141 23.02.2014 19:25 # −4
anonimb84a2f6fd141 23.02.2014 19:26 # −4
xyilka 23.02.2014 19:33 # −11
xyilka 23.02.2014 19:33 # −11
xyilka 23.02.2014 19:35 # −11
xyilka 23.02.2014 19:36 # −11
xyilka 23.02.2014 19:37 # −11
xyilka 23.02.2014 19:37 # −6
anonimb84a2f6fd141 23.02.2014 19:38 # −5
anonimb84a2f6fd141 23.02.2014 19:38 # −5
anonimb84a2f6fd141 23.02.2014 19:38 # −5
anonimb84a2f6fd141 23.02.2014 19:38 # −5
xyilka 23.02.2014 19:38 # −11
anonimb84a2f6fd141 23.02.2014 19:39 # −4
xyilka 23.02.2014 19:39 # −11
anonimb84a2f6fd141 23.02.2014 19:39 # −4
anonimb84a2f6fd141 23.02.2014 19:39 # −4
anonimb84a2f6fd141 23.02.2014 19:39 # −4
xyilka 23.02.2014 19:39 # −11
anonimb84a2f6fd141 23.02.2014 19:40 # −3
anonimb84a2f6fd141 23.02.2014 19:40 # −3
xyilka 23.02.2014 19:40 # −11
anonimb84a2f6fd141 23.02.2014 19:40 # −3
xyilka 23.02.2014 19:41 # −11
xyilka 24.02.2014 14:54 # −14
Soul_re@ver 23.02.2014 15:32 # 0
Вот же говно!
Konardo 23.02.2014 15:45 # −22
3.14159265 23.02.2014 15:44 # +2
Konardo 23.02.2014 15:44 # −21
TarasB 23.02.2014 15:54 # +1
Это другой чел, который нарвался на баг в моём крестопроекте, которые не проявляется в студии.
Неделю пытались понять, почему такая хуйня.
Теперь поняли. Плавающийпитухпроблемы.
3.14159265 23.02.2014 16:27 # 0
Сдается мне что там пахнет UB и gcc сделал тебе spoint.DoTrollFace(f).
>>Это другой чел, который нарвался на баг в моём крестопроекте, которые не проявляется в студии.
А-а. То есть по-прежнему непортируемый мс-онли код.
TarasB 23.02.2014 17:24 # −1
Мы вдвоём неделю искали, почему он оказался мс-онли.
3.14159265 23.02.2014 16:56 # 0
http://artdesign21.narod.ru/image/1/ko_034.jpg
bormand 23.02.2014 17:23 # +4
Все единички, баг повторить не удалось ;(
P.S. gcc любит оптимизировать операции с флоатами оставляя их в регистрах сопроцессора (вспомни мой пост о sin(x) != sin(x). Возможно проблема в этом. Как экстендеды они не равны, а когда меняешь и суешь во флоат - ниче не меняется.
UPD: А что делает DoCorrectFace?
TarasB 23.02.2014 17:38 # 0
Двигает точку p так, чтобы face.dist(p) стало <= 0.0f
Проблема в том, что на бумаге написать, как надо двигать, очень просто. А чтоб на компе было ок - тяжело.
3.14159265 23.02.2014 18:01 # 0
Hello World!
Initial p:
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0))
Corrected:
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0))
Done: 0
Может это винды. На луникс влом ребутить.
bormand 23.02.2014 18:06 # 0
> На луникс влом ребутить.
Вот на луниксе баг почему-то не получилось повторить.
P.S. Есть вероятность, что от вывода баг пройдет, как и тогда с синусами. Что очень хреново ;(
TarasB 23.02.2014 18:08 # 0
именно поэтому мы неделю и не могли его поймать
bormand 23.02.2014 18:13 # +1
Тогда опция -ffloat-store по идее уберет баг.
Но все-таки зря ты сравниваешь с 0. Имхо, стоит взять какой-то маленький эпсилон и сравнивать с ним. Если один объект воткнется в другой на тысячную часть пикселя - никто не заметит.
TarasB 23.02.2014 18:20 # 0
Я-то думал, что уж на таких трюизмах-то можно забить на эпсилоны, а вот хуй, нельзя.
bormand 23.02.2014 18:23 # 0
А вот в SSE флоаты и даблы настоящие, поэтому у меня баг не проявился ;(
TarasB 23.02.2014 18:26 # 0
А есть ли портабельный какой-нибидь
__pitux_gcc_builtin_set_fpy_precision?
bormand 23.02.2014 18:35 # 0
Ну нету у FPU float'а, нету. Его можно только сэмулировать через выгрузку-загрузку в память. Что и делает -ffloat-store.
По идее портабельным решением будет volatile переменная. Компилятор не сможет убрать запись и чтение, и все будет норм.
P.S. Кстати баг, подобный твоему, когда-то был в пыхе. И он позволял специально подобранным числом повешать к хуям то ли парсер флоатов то ли конвертер флоата в строку.
TarasB 23.02.2014 18:49 # +2
bormand 23.02.2014 18:58 # 0
А, ты вон про че... Я уже и забыл, что у штеудов такой флаг был...
TarasB 23.02.2014 19:01 # +1
И я его ставил в дельфийском хулионе. Для ускорения типа.
bormand 23.02.2014 19:05 # +1
Кстати, вот очередной пример, когда глобальное состояние это очень хуёвая идея. Была бы эта точность в самой команде (например как в sse - разные инструкции для разной точности), а не в control word - таких проблем бы не было.
3.14159265 23.02.2014 19:25 # 0
С другой стороны, создавать десяток почти одинаковых команд - усложнять декодер, жизнь кодерам, лишние байты в коде команды, особенно когда надо выполнить пачку - алгоритм. Оно ж для программеров на асме - байтоёбов по-опеределению.
И меня честно говоря уже раздражает насколько сильно распух ассемблер для последних интелов.
Смутно вспоминаю срачи, когда у интела была избыточная точность и она кому-то мешала, что они запилили сиё.
bormand 23.02.2014 19:15 # 0
На сколько процентов ускоряет? Есть статистика?
3.14159265 23.02.2014 19:07 # 0
Через год представляю картину: Тарас портирует хулион на ARM.
Джве недели постигали где баг армоблядском проце...
bormand 23.02.2014 19:08 # +2
3.14159265 23.02.2014 19:12 # +1
О сколько нам открытий чудных
Готовит плавальный питух.
И опыт, сын багов коварных,
И гцц - кодеров друг.
TarasB 23.02.2014 20:04 # 0
3.14159265 23.02.2014 18:53 # 0
Интересно. А тут, на гкоде такое было?
3.14159265 23.02.2014 18:27 # 0
Убирает.
> стоит взять какой-то маленький эпсилон и сравнивать с ним
+1
bormand 23.02.2014 18:35 # 0
3.14159265 23.02.2014 18:39 # 0
Зато int ad - да!
bormand 23.02.2014 18:42 # 0
O_o. Но почему?
А ну хотя. Оно же не влияет на вычисления, которые приводят к кривому ad. Там тогда всю цепочку вычислений надо через volatile прогонять...
anonimb84a2f6fd141 23.02.2014 18:45 # −4
3.14159265 23.02.2014 18:47 # 0
volatile float x,y,z; тоже. Мне кажется если ставить то там, что поставит КРЕСТ на скорости.
Последнее приводит только к изменению from_int(0xc166e2d0)) на from_int(0xc166e2d1)) - то есть как без оптимизаций, но done у меня и без оптимизаций false.
bormand 23.02.2014 18:52 # −1
Не, оно не рекомендация. Просто точность теряется на минусе в dist(). Вот туда если добавляешь volatile переменные - баг проходит. Но это не решение проблемы ;(
А проблема тут в том, что у интеловского FPU нет флоатов.
anonimb84a2f6fd141 23.02.2014 18:53 # −3
3.14159265 23.02.2014 19:03 # 0
Ну как это нет? Внутри нет, а чтобы сохранять/загружать из памяти есть.
Может printfы и конвертят таким образом в single precision? Мы же надеялись на то что volatile прогонит через память.
3.14159265 23.02.2014 18:18 # −1
gcc 4.82 без O
На всех итерациях (штук 20): 32CFDDE8. На последней: B54DA3CE.
g++ -Wall -O3
Initial p:
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0))
Corrected:
B5551390
Point3D(from_int(0x41c6940e), from_int(0x427352a6), from_int(0xc166e2d0))
Done: 1
bormand 23.02.2014 18:50 # 0
> На всех итерациях (штук 20): 32CFDDE8. На последней: B54DA3CE.
Именно так.
TarasB 23.02.2014 18:08 # −1
точка НЕ изменилась, но возвращаемый результат ноль говорит, что точка была некорректной, то есть её таки меняли
http://ideone.com/C5koEO
зацените возвращаемый результат
3.14159265 23.02.2014 18:15 # −1
Я понял. -O1 и выше там нормально.
anonimb84a2f6fd141 23.02.2014 18:45 # −5
anonimb84a2f6fd141 23.02.2014 18:47 # −4
anonimb84a2f6fd141 23.02.2014 18:47 # −4
3.14159265 23.02.2014 18:26 # −1
У меня Done: 0 всегда с любыми O (без принтов).
Единственное отличие from_int(0xc166e2d0)) и from_int(0xc166e2d1)).
Видать действительно в регистрах кешится, а принты каким-то образом очищают это.
bormand 23.02.2014 18:28 # 0
Ну вспомни код, который я кидал давным-давно. Там два синуса давали разный результат. Если выводишь один из них - все равно багует. Выводишь оба - оп, и нету бага. Настоящий баг шрёдингера ;)
3.14159265 23.02.2014 18:29 # 0
TarasB 23.02.2014 18:51 # 0
Можно ли считать, что мой крестоскилл за эти недели вырос так, как он не вырос за год до этого?
anonimb84a2f6fd141 23.02.2014 18:52 # −3
Abbath 23.02.2014 21:47 # 0
bormand 23.02.2014 22:00 # 0
bormand 23.02.2014 22:02 # 0
Сорри, его не я постил. Я сраный плагиатор ;(
3.14159265 23.02.2014 23:33 # +1
Комментарии с анализом получили больше плюсов чем сам ГК.
Dummy00001 23.02.2014 18:11 # −1
("На луникс влом ребутить.": ставь виртуалбокс, ставь какой дебьян без гуя (или с xfce). 512М памяти и 20Г диска хватает за глаза. если хочешь совсем свежак ставь дебьян sid (aptosid), но его надо апдейтить часто (как минимум раз в месяц). и он ломается иногда когда миграции происходят - https://release.debian.org/transitions/ - но меня как вторичная/третичная система устраивает.)
надо epsilon добавить на строке 64 попробовать.
bormand 23.02.2014 18:19 # −1
Ну вот у меня 64 битная ось. И, как я понимаю, наличие SSE на такой платформе подразумевается. Поэтому gcc собрал код через sse, и точность выше флоата не подскочила - бага нет.
У Тараса SSE нет (целерон 600), все считается на FPU, и проявляется баг.
Dummy00001 23.02.2014 18:25 # −1
да и вроде же gcc SSE без пинка не подключает. по крайней мере раньше надо было -march/-mcpu задавать - просто -О не хватало.
bormand 23.02.2014 18:28 # −1
На 32 же по дефолту стоят весьма консервативные march/mcpu. Что-то типа 386 или 686. Поэтому там и надо указывать...
3.14159265 23.02.2014 18:32 # −1
Dummy00001 23.02.2014 18:32 # −1
к сожалению у меня для 32бит нет окружения - с -m32 ничего не компилится вообще.
bormand 23.02.2014 18:37 # −1
Аналогично, надо бы установить.
3.14159265 23.02.2014 18:12 # −1
unknown software exception (0xc0000096) в приложении по адресу 0x00405025.
ВНЕЗАПНО
TarasB 23.02.2014 18:20 # −1
3.14159265 23.02.2014 18:22 # −1
anonimb84a2f6fd141 23.02.2014 18:46 # −4
3.14159265 23.02.2014 18:56 # +3
God made natural numbers; all else is the work of man
Leopold Kronecker
http://cache.desktopnexus.com/thumbnails/695809-bigthumbnail.jpg