я раньше встречал упоминание, что CPU обрабатывает вещественные числе представленные в double
и при использовании float перед каждой операцией происходит преобразование типа числа
S>судя по этому документы это уже не так IEEE Floating-Point Representation
Студия здесь не при делах.
По указанному адресу описан стандарт IEEE-754.
Который и реализован в микропроцессоре.
Более того, все операции с плавающей точкой происходят на плавающих регистрах, которые еще и устроены в виде стека.
Размер регистра = 80 бит, 64 бита мантисса, 15 бит — порядок.
При загрузке в регистр и float, и double расширяются до 80 бит.
Но в интеле есть еще много других регистров, которые тоже работают с плавающими числами.
Например, ХMM.
А чего там в системе команд AVX сделано, я даже и не знаю.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: представление вещественных чисел в Visual Studio
Здравствуйте, sergey2b, Вы писали:
S>я раньше встречал упоминание, что CPU обрабатывает вещественные числе представленные в double S>и при использовании float перед каждой операцией происходит преобразование типа числа
Вашему описанию соответствуют две совершенно разные вещи.
Первая — это как вещественные числа представляются в CPU во время операций с ними и при хранении в своих регистрах. В случае x86, в 32-битном режиме нормой было использование FPU, у которого внутренний формат с 64 битами мантиссы (это даже не double, это то, что в нормальных местах зовётся long double). Вычисления производятся с ним, но результаты могут округляться на каждой операции до одинарной или двойной точности. Этот режим рулится у MS через функции типа _control87, умолчание, насколько помню — усечение до double.
В x86-64 студия, судя по документации, использует только SSE, у которого раздельные операции для одинарной и двойной точности, при этом long double зачем-то сделано алиасом для double, то есть FPU из C/C++ не применить совсем.
В Linux и близких системах такого тупого форсирования нет, есть только предпочтение — FPU в 32 битах и SSE в 64 (обычно можно крутить опциями компиляции).
Вторая — это выполняется ли в C правило, что float при любой арифметической операции преобразуется в double. Это правило было в K&R, отменено точно в C99, но я не знаю с ходу про промежуточные стадии и про реализацию у таких своенравных авторов, как MS.
S>судя по этому документы это уже не так IEEE Floating-Point Representation
S>какой вещественный тип лучше использовать с точки зрения оптимизации по скорости
float (одинарный), почти всегда. Даже если операции делаются одинаково, меньше возни с памятью.
The God is real, unless declared integer.
Re[2]: представление вещественных чисел в Visual Studio
Здравствуйте, LaptevVV, Вы писали:
S>>судя по этому документы это уже не так IEEE Floating-Point Representation LVV>Студия здесь не при делах.
При делах.
LVV>По указанному адресу описан стандарт IEEE-754. LVV>Который и реализован в микропроцессоре.
Вы плохо читаете. Там написаны совершенно конкретные вещи (местами очень характерно неправильные):
— "Microsoft C++ (MSVC) is consistent with the IEEE numeric standards." (всем? предложение явно некорректно).
— чему соответствуют float и double компилятора (тут ok — и в этом главная полезная конкретика документа).
— чему соответствует long double компилятора (в первый раз — что он равен double во внешнем хранении — "long double data type is treated as a distinct type, but the storage type maps to double" — то есть нафиг такой не нужен, но чуть ниже говорится про 15 бит порядка и 64 мантиссы (significand) — то есть сами себе противоречат).
— "There are at least five internal formats for floating-point numbers that are representable in hardware targeted by the MSVC compiler." Судя по списку — сюда включён quadruple-precision (128 бит), который на x86 обычно не водится (PPro не считаем) — значит, врут про поддержку железа (хотя раз компилятор не умеет — то пофиг, для юзера студии ничего не меняется).
— Что IEEE описывает "double-extended-precision (10-byte) format" — врут. На самом деле, да, есть "extended double" как рекомендация по минимальным свойствам параметров таких типов, но не конкретная реализация (никто там не обязан укладывать его в 10 байт, не использовать скрытую единицу, и так далее).
Дальше, да, идёт информация из IEEE754. Но эта начальная часть, написанная словно тем журналистом, которого изнасиловали учёные авторы реальных описаний, очень показательна для MS — и приводит в итоге к очень простому выводу — не используйте ничего кроме float и double, иначе вас укусят за бочок, причём в самый неожиданный момент. А для standard lawyerʼа это, кроме примера как не надо писать, ещё и показательнейший документ о подводных течениях и историческом развитии.
LVV>Более того, все операции с плавающей точкой происходят на плавающих регистрах, которые еще и устроены в виде стека.
И это никак не меняет суть самих вычислений.
LVV>Размер регистра = 80 бит, 64 бита мантисса, 15 бит — порядок. LVV>При загрузке в регистр и float, и double расширяются до 80 бит.
А потом сужаются, при выгрузке. А ещё могут округляться по ходу вычислений. И это куда важнее, чем просто расширенное хранение.
LVV>Но в интеле есть еще много других регистров, которые тоже работают с плавающими числами.
Регистры с числами не работают, они их хранят. С числами работают инструкции.
LVV>Например, ХMM. LVV>А чего там в системе команд AVX сделано, я даже и не знаю.
Ну тогда я вам подскажу: AVX работает с теми же типами данных теми же операциями, что SSE — с float и double, на тех же XMM регистрах (могут их расширять в AVX2 и AVX512, тип данных сохраняется). 80-битного формата там нет.
The God is real, unless declared integer.
Re[2]: представление вещественных чисел в Visual Studio
N>Вычисления производятся с ним, но результаты могут округляться на каждой операции до одинарной или двойной точности. Этот режим рулится у MS через функции типа _control87
Не совсем. До заданной точности округляется не весь результат операции, а только его мантисса. И используя только fpu control word нельзя без дополнительных приседаний получить вычисления как в float или как в double из IEEE754.
То есть такая функция может и будет выдавать разный результат при вычислении через sse и через i387 вне зависимости от значения fpu control word:
float f(float m) {
return m * 8.0f / 8.0f;
}
(например, если вызвать её с очевидным аргументом f(FLT_MAX); но и с малыми числами возникает аналогичная проблема).
Чтобы получить именно поведение float или double на i387, нужно дополнительно форсировать усечение и экспоненты числа, а не только мантиссы. Например gcc с опцией -ffloat-store умеет это делать через постоянную выгрузку значений в память, что влечёт за собой правильную обработку экспоненты, но, конечно, замедляет вычисления (но на i387 особо другого выбора нет, если нужно именно совместимые и предсказуемые вычисления в рамках IEEE754).
Re: представление вещественных чисел в Visual Studio
Здравствуйте, sergey2b, Вы писали:
S>я раньше встречал упоминание, что CPU обрабатывает вещественные числе представленные в double S>и при использовании float перед каждой операцией происходит преобразование типа числа
S>судя по этому документы это уже не так IEEE Floating-Point Representation
S>какой вещественный тип лучше использовать с точки зрения оптимизации по скорости
С точки зрения оптимизации по скорости следует всегда профилировать и всегда контролировать скорость (обычно throughput).
На практике разницу в размере данных кэш процессора сглаживает вполне себе успешно и вычисления что с float что с double выполняются примерно 99% с одинаковой скоростью, но бывают ньюансы.
ps: кстати при распаралеливании можно получать разные результаты так как (a+b)+c != a+(b+c)
Здравствуйте, watchmaker, Вы писали:
N>>Вычисления производятся с ним, но результаты могут округляться на каждой операции до одинарной или двойной точности. Этот режим рулится у MS через функции типа _control87 W>Не совсем. До заданной точности округляется не весь результат операции, а только его мантисса.
Эээ
_порядок_ не может _округляться_, очевидно. Он может только усекаться.
Да, в то, что у промежуточного хранения шире диапазон порядков, я намеренно не стал углубляться.
(Тут можно было бы обсудить поведение денормализованных, но уже облом.)
W>float f(float m) { W> return m * 8.0f / 8.0f; W>} W>(например, если вызвать её с очевидным аргументом f(FLT_MAX); но и с малыми числами возникает аналогичная проблема).
Всё верно, спасибо, но я посчитал это излишним для исходной темы.
W>Чтобы получить именно поведение float или double на i387, нужно дополнительно форсировать усечение и экспоненты числа, а не только мантиссы. Например gcc с опцией -ffloat-store умеет это делать через постоянную выгрузку значений в память, что влечёт за собой правильную обработку экспоненты, но, конечно, замедляет вычисления (но на i387 особо другого выбора нет, если нужно именно совместимые и предсказуемые вычисления в рамках IEEE754).
[q] Use '-ffloat-store' for such programs, after modifying them to store all pertinent intermediate computations into variables./[q]
ещё и сохранять в переменные все промежуточные значения даже какого-нибудь b*b-4*a*c... вывернуться применить такое, конечно, можно, но код будет ужасен. Не вижу большой пользы в этой опции.
The God is real, unless declared integer.
Re[3]: представление вещественных чисел в Visual Studio
S>>>судя по этому документы это уже не так IEEE Floating-Point Representation LVV>>Студия здесь не при делах. N>При делах.
ну, тогда, если уж быть ТОЧНЫМ — это все касается компилятора, а не студии...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: представление вещественных чисел в Visual Studio
Здравствуйте, LaptevVV, Вы писали:
S>>>>судя по этому документы это уже не так IEEE Floating-Point Representation LVV>>>Студия здесь не при делах. N>>При делах. LVV>ну, тогда, если уж быть ТОЧНЫМ — это все касается компилятора, а не студии...
Её штатного компилятора, идущего по умолчанию и используемого подавляющим большинством пользователей.