9

以前の K&R (第 2 版) および私が読んだ他の C 言語のテキストでは、動的メモリ アロケータの実装について次のように説明されていmalloc()ますfree()。どうやら、特定のコンピューター ハードウェア アーキテクチャ (CPU、レジスタ、およびメモリ アクセス) によって、特定の値の型を格納およびアドレス指定する方法が制限されているようです。たとえば、4longの倍数のアドレスから始まる 4 バイト ( ) の整数を格納する必要がある場合があります。

メジャー プラットフォーム (Intel & AMD、SPARC、Alpha) がメモリ割り当てとメモリ アクセスに課す制限はありますか? または、特定のアドレス境界でのメモリ割り当ての調整を安全に無視できますか?

4

5 に答える 5

6

Sparc、MIPS、Alpha、およびその他のほとんどの「従来の RISC」アーキテクチャでは、現在でもメモリへのアライン アクセスしか許可されていません。アラインされていないアクセスは例外を引き起こしますが、一部のオペレーティング システムは、より小さなロードとストアを使用してソフトウェアで目的のアドレスからコピーすることによって例外を処理します。アプリケーション コードは、パフォーマンスが非常に悪くなることを除けば、問題があったことを認識しません。

MIPS には、アラインされていないアドレスから 32 ビット量にアクセスするために使用できる特別な命令 (lwl および lwr) があります。コンパイラは、アドレスがアラインされていない可能性が高いと判断できる場合は常に、通常の lw 命令の代わりにこの 2 つの命令シーケンスを使用します。

x86 はハードウェアで非整列メモリ アクセスを例外なく処理できますが、整列アクセスと比較して最大 3 倍のパフォーマンス ヒットがまだあります。

Ulrich Drepper は、これとその他のメモリ関連のトピックに関する包括的な論文、What Every Programmer Should Know About Memoryを書きました。非常に長い記事ですが、歯ごたえの良さが詰まっています。

于 2008-09-06T05:57:36.547 に答える
4

アライメントは今日でも非常に重要です。一部のプロセッサ (68k ファミリが思い浮かびます) は、奇数境界でワード値にアクセスしようとすると、例外をスローします。今日、ほとんどのプロセッサは 2 つのメモリ サイクルを実行して非整列ワードをフェッチしますが、これは整列フェッチよりも明らかに遅くなります。他の一部のプロセッサは例外をスローしませんが、メモリから間違った値を取得します!

パフォーマンス以外の理由がない場合は、プロセッサの配置設定に従うことをお勧めします。通常、コンパイラがすべての詳細を処理しますが、メモリ構造を自分でレイアウトする場合は、検討する価値があります。

于 2008-08-30T23:11:51.990 に答える
1

C(++) でクラスまたは構造体をレイアウトするときは、アラインメントの問題に注意する必要があります。このような場合、コンパイラは正しいことを行いますが、構造体/クラスの全体的なサイズが必要以上に無駄になる可能性があります。

例えば:

struct
{ 
    char A;
    int B;
    char C;
    int D;
};

サイズは 4 * 4 = 16 バイトになります (x86 上の Windows を想定)。

struct
{ 
    char A;
    char C;
    int B;
    int D;
};

サイズは 4*3 = 12 バイトになります。

これは、コンパイラが整数に対して 4 バイトのアラインメントを強制するのに対し、文字に対しては 1 バイトのみを強制するためです。

一般に、無駄なスペースを最小限に抑えるために、同じサイズ (型) のメンバー変数をまとめてパックします。

于 2008-08-30T23:22:35.707 に答える
1

IA-32 および AMD64 でも、一部の SSE 命令/組み込み関数は整列データを必要とすることに注意してください。データが整列されていない場合、これらの命令は例外をスローするため、少なくとも「間違ったデータ」のバグをデバッグする必要はありません。同等のアラインされていない命令もありますが、デントンが言うように、それらは遅いです。

VC++ を使用している場合は、#pragma pack ディレクティブの他に、正確な位置合わせのための __declspec(align) ディレクティブもあります。VC++ のドキュメントでは、特定のアラインメント要件について __aligned_malloc 関数についても言及されています。

経験則として、コンパイラ/言語間でデータを移動したり、SSE 命令を使用したりしない限り、アライメントの問題はおそらく無視できます。

于 2008-09-06T06:19:35.777 に答える
1

グレッグが述べたように、それは今日でも重要であり (おそらくいくつかの点でより重要です)、コンパイラは通常、アーキテクチャのターゲットに基づいてアライメントを処理します。管理された環境では、JIT コンパイラはランタイム アーキテクチャに基づいてアラインメントを最適化できます。

アラインメントを変更するプラグマ ディレクティブ (C/C++) が表示される場合があります。これは、非常に具体的な配置が必要な場合にのみ使用してください。

// For example, this changes the pack to 2 byte alignment.
#pragma pack(2)
于 2008-08-31T01:32:57.063 に答える