2008-08-30 6 views
8

古いK & R(第2版)とmalloc()free()のスタイルで動的なメモリアロケータの実装を議論し、私が読んだ他のC言語のテキスト通常も言及、渡して、データ型の整列制限に関するもの。明らかに特定のコンピュータハードウェアアーキテクチャ(CPU、レジスタ、およびメモリアクセス)は、特定の値の型を格納およびアドレス指定する方法を制限しています。例えば、4の倍数であるアドレスから始まる4バイト(long)整数を格納しなければならないという要件が存在する可能性がある。境界調整の制約()/ free()を

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

答えて

4

今日でもアライメントはまだ非常に重要です。あなたが奇数の境界で単語の値にアクセスしようとすると、いくつかのプロセッサ(68kファミリが頭に浮かぶ)は例外をスローします。今日では、ほとんどのプロセッサは2つのメモリサイクルを実行してアライメントの合っていないワードをフェッチしますが、これは確実にアライメントされたフェッチよりも遅くなります。他のプロセッサでも例外はスローされませんが、がメモリから正しくの値をフェッチします!

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

1

C(++)でクラスまたは構造体をレイアウトするときに、アラインメントの問題に注意する必要があります。これらのケースでは、コンパイラはあなたのために正しいことを行うだろうが、構造体/クラスの全体的なサイズは、例えば、必要な

よりwastefullことがあります

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バイト整列を強制しますが、charには1バイトしか適用しないためです。一緒に同じ大きさ(タイプ)の一般的なパックのメンバ変数で

は無駄な空間を最小にします。

1

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

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

// For example, this changes the pack to 2 byte alignment. 
#pragma pack(2) 
6

SPARC、MIPS、Alphaの、そして唯一の整列許可し、他のほとんどの "古典的なRISC" アーキテクチャは、今日でも、メモリへのアクセス。非整列アクセスは、例外が発生しますが、一部のオペレーティング・システムは、より小さなロードとストアを使用してソフトウェアで所望のアドレスからコピーすることによって、例外を処理します。アプリケーションコードは、パフォーマンスが非常に悪くなることを除いて、問題があることを認識しません。

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

x86は、ハードウェア内の例外を除いて、アライメントされていないメモリアクセスを処理できますが、アライメントされたアクセスと比較して最大3倍のパフォーマンスヒットがあります。

Ulrich Drepperは、このようなメモリ関連トピックに関する包括的な論文What Every Programmer Should Know About Memoryを書きました。それは非常に長い書き起こしですが、歯ごたえがあります。

1

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

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

コンパイラ/言語間でデータを移動している場合や、SSE命令を使用している場合を除き、アラインメントの問題は無視される可能性があります。

関連する問題