13

誰かが私に言った:

x86-64では、FP演算はSSEで行われるため、longdoubleは64ビットです。

しかし、x86-64 ABIでは、次のように述べています。

Cタイプ のサイズ アラインメント AMD64アーキテクチャ
ロングダブル 16 16 80ビット拡張(IEEE-754)

参照:amd64-abi.pdf

そしてgccsizeof(long double)は16であると言い、 FLT_DBL=1.79769e+308FLT_LDBL = 1.18973e+4932

混乱していますが、long double64ビットはどうですか?80ビット表現だと思いました。

4

3 に答える 3

11

x86-64では、FP演算はSSEで行われるため、longdoubleは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;
}

アセンブリ出力では、製品と製品(両方のSSE命令)が見つかりmulsd xmm1, xmm0ましたが、製品(x87命令)が見つかりました。doublemulss xmm0, xmm2floatfmulp st(1), stlong double

したがって、コンパイラは可能な場合はSSEを使用しますが、古いx87命令セットを介して80ビットの精度の計算を許可することが確認されています。


これはコンパイラ固有であることに注意してください。一部のコンパイラ(VC ++など)は常に80ビットの精度の型を無視long doubleし、の同義語として扱われdoubleます。

一方、x86-64 System V ABI(Linuxで採用)long doubleは80ビットを義務付けているため、コンパイラがこのタイプの利用可能なすべての精度を使用して計算を実行する唯一の方法は、x87命令を使用することです。

于 2013-03-02T16:00:11.007 に答える
4

AMD ABIは、Cタイプが何であるかを実際に強制することはできlong doubleません。これは、そうする管轄権/権限がないためです。各C実装は、C標準(C実装が標準に準拠している場合)に従って、タイプが何であるかを独自に指定でき、各C実装は、AMDABIに準拠するかどうかを選択できます。

long doubleつまり、「 x86-64には何がありますか?」と単純に尋ねることはできません。long double特定のC実装に何があるかを尋ねる必要があります。これは、コンパイルに使用される特定のCコンパイラ、バージョン、およびスイッチを指定することを意味します。(コンパイラには、1つの設定long doubleで64ビットのバイナリIEEE 754浮動小数点オブジェクトが作成され、別の設定long doubleで80ビットのIntel浮動小数点オブジェクトが作成されるスイッチがある場合があります。技術的には、コンパイラ、バージョン、およびスイッチのそれぞれの異なる組み合わせは別個のC実装です。)

64ビットのバイナリIEEE-754浮動小数点オブジェクトとして実装するコンパイラはlong double、AMDABIが呼び出すものとしてそれらを渡すだけdoubleです。ABIが呼び出すものとしてそれらを渡すことはありませんlong double。そうすることで、コンパイラのこの側面は、long double同様に処理する他のソフトウェアとのみ互換性があります。

于 2013-03-03T11:27:31.820 に答える
0

SSE計算は倍精度であり、中間表現は64ビットです。

long doubleあなたが指摘したように、それはそうではありません。64ビット値は、計算後にlongdoubleに書き込まれるだけです。

于 2013-03-02T15:49:23.223 に答える