2013-03-02 2 views
4

Кто-то сказал мне, что:Что такое long double on x86-64?

Под x86-64, FP арифметика выполняется с SSE, и поэтому долго двойные 64 бита.

Но в x86-64 ABI говорится, что:

C type | sizeof | alignment | AMD64 Architecture 
long double | 16 | 16  | 80-bit extended (IEEE-754) 

См: amd64-abi.pdf

и НКУ говорит sizeof(long double) 16 и дает FLT_DBL = 1.79769e+308 и FLT_LDBL = 1.18973e+4932

Я 'confused, как long double 64 бит? Я думал, что это 80-битное представление.

+3

Является ли этот «кто-то» более авторитетным, чем AMD64 ABI? Если нет, то каков ваш вопрос в точности? – Mat

+0

@Mat: Кто-то прав в некотором роде? –

+0

@user Что заставляет вас думать, что amd64 ABI ошибочен? –

ответ

7

Под x86-64 Арифметика FP выполняется с помощью SSE, поэтому длинный двойной бит - 64 бит.

Вот что обычно бывает под x86-64 (где наличие инструкций SSE гарантируется), но программа по-прежнему свободно использовать x87, к которому компилятор может прибегнуть при использовании long double.

Вы можете подтвердить это путем компиляции программы, как это с g++ на Linux:

#include <iostream> 
#include <cstdlib> 
#include <ctime> 

int main() 
{ 
    std::srand(std::time(NULL)); 
    float f1=rand(), f2=rand(); 
    double d1=rand(), d2=rand(); 
    long double l1=rand(), l2=rand(); 

    std::cout<<f1*f2<<" "<<d1*d2<<" "<<l1*l2<<std::endl; 
    return 0; 
} 

В выходе сборки, я нахожу mulsd xmm1, xmm0 для double продукта и mulss xmm0, xmm2 для float продукта (обе инструкции SSE), но fmulp st(1), st (инструкция x87) для продукта long double.

Итак, это подтверждается, что компилятор использует SSE, когда он может, но все же допускает вычисления с 80-битной точностью через старый набор команд x87.


Обратите внимание, что это компилятор конкретных - некоторые компиляторы (например, VC++) всегда игнорировали 80-битные типы точности и только обработанные long double как синоним double.

С другой стороны, поскольку система x86-64 V ABI (принятая в Linux) предусматривает, что long double - это 80 бит, единственный способ для компилятора выполнить вычисления с использованием всей доступной точности этого типа - использовать x87.

+0

* «Обратите внимание, что это зависит от компилятора» * - Какой из них вы использовали при проверке дизассемблирования, приведенной в этом ответе? * «VC++ всегда игнорировал 80-битные типы точности» * - Это неверно. До и включая Visual Studio 6, тип данных «long double» использовал 80-битное расширенное представление. – IInspectable

+0

@Инспективный: хех, кто знает, прошло уже три года; вероятно, что бы ни было включено в производную Ubuntu, которую я использовал в то время, это может быть gcc 4.6. Во всяком случае, быстрый тест (с более простым [более четким тестовым примером] (https://godbolt.org/g/TgQr9a)) показывает, что сгенерированный код практически идентичен всем доступным компиляторам x86_64 ('mulsd' для' double ',' mulss' для 'float',' fmulp' для 'long double'). –

+0

@Inspectable: для VC++ моя ссылка, вероятно, была https://msdn.microsoft.com/en-us/library/9cx8xs15(v=vs.71).aspx, в которой говорится, что все 32-разрядные версии VC++ игнорируют 80-битные 'long double':« Предыдущие 16-разрядные версии Microsoft C/C++ и Microsoft Visual C++ поддерживают «длинный двойной», 80-битный тип данных с высокой точностью. Однако в программировании Win32 тип данных «long double» сопоставляется с типом данных «double», 64-bit precision. ». Я уверен, что это имеет место в VC++ 2002 и более поздних версиях, однако у меня нет установки VC++ <= 6, чтобы проверить это с более ранними версиями. –

0

Расчет SSE является двойной точностью, а промежуточное представление - 64 бит.

Это не long double, как вы указали. 64-разрядное значение просто записывается в длинный двойной после вычисления.

+0

Я не последовал за тобой. Если я использую тип «long double», это арифметика, выполняемая с 80-битной точностью? –

+0

@ user1131467 расширенный. вам придется посмотреть на asm для окончательного ответа на заданный набор настроек сборки. компилятор может использовать либо FPU (80 бит), либо SSE2 (64-разрядный). – justin

+0

Я декомпилировал дополнение, он использует, например, 'FADDP' и'% st' и '% st (1)' регистр. Думаю, это похоже на fpu. –

5

AMD ABI не может фактически заставить то, что тип C long double, потому что у него нет юрисдикции/полномочий для этого. Каждая реализация C может составить свою собственную спецификацию типов, с учетом стандарта C (если реализация C соответствует стандарту), и каждая реализация C может выбрать, следует ли соответствовать AMD ABI.

Это означает, что вы не можете просто спросить «Что такое long double на x86-64?». Вы должны спросить, что такое long double в конкретной реализации С. Это означает указание конкретного компилятора, версии и коммутаторов, используемых для компиляции. (У компилятора может быть переключатель, для которого один параметр делает long double 64-битным двоичным объектом IEEE 754 с плавающей точкой, а другой параметр делает long double 80-битным объектом с плавающей точкой Intel. Технически каждая комбинация компилятора, и переключатели являются отличной реализацией C.)

Компилятор, который реализует long double как 64-битный двоичный объект с плавающей точкой IEEE-754, просто передает их как то, что AMD ABI вызывает double; он никогда не передает их, как ABI вызывает long double. При этом этот аспект компилятора будет совместим только с другим программным обеспечением, которое относится к long double аналогичным образом.

+0

Ваша формулировка немного странная. Необходимо, чтобы пользовательские приложения соглашались с ядром о размере, выравнивании и представлении типов - в противном случае системные вызовы не будут работать. Это функция ABI. В этом смысле ABI «заставляет» приложения подчиняться ему, потому что, если они этого не делают, они не будут работать (по крайней мере, когда они попытаются сделать системные вызовы). –

+0

@ user1131467: (1) Данное ядро ​​может не придерживаться AMD ABI. (2) На некоторых платформах системные вызовы абстрагируются библиотекой пользовательского пространства, снабженной средой C, которая может исправлять любые такие несоответствия импеданса. –

+1

@ StephenCanon: Да, строго говоря, это не «AMD ABI» или «x86-64 ABI», это «System V x86-64 ABI». Linux предпочитает придерживаться этого, Windows этого не делает. –

Смежные вопросы