2009-06-28 19 views
11

Pentiumなどの32ビットIntelプロセッサは、64ビット幅のデータバスを持つため、1アクセスあたり8バイトをフェッチします。これに基づいて、私は、これらのプロセッサがアドレスバス上で放出する物理アドレスが常に8の倍数であると仮定しています。32ビットIntelプロセッサでのメモリアライメント

まず、この結論は正しいですか?

第2に、正しい場合は、データ構造体のメンバーを8バイト境界に揃える必要があります。しかし、私はこれらのプロセッサではなく、4バイトのアライメントを使用する人たちを見てきました。

どのようにして正当化できますか?

+1

私はこの質問が何を意味するのか分かりませんが、これがプログラミングにどのように関係しているのか、そしてこれがどのように私に影響するのかに興味を持っています。この低レベルタイプのものの基本的なイントロをどこで読むことができますか? –

+4

「すべてのプログラマがメモリについて知っておくべきこと」を参照してください:http://people.redhat.com/drepper/cpumemory.pdf – Crashworks

+1

「要求された読み込みは常に8の倍数です。 8バイトの境界 "?私はこれらの間の論理的な接続を見ません。データが8バイトの境界を横切っていない限り、私たちは良いですね。 – jalf

答えて

14

通常の経験則(IntelsとAMDの最適化マニュアルからまっすぐです)は、すべてのデータ型を独自のサイズで整列させる必要があります。 int32は32ビット境界に、int64は64ビット境界にアライメントしなければなりません。 charはどこにでもうまく収まるでしょう。

もう1つの経験則は、もちろん「コンパイラはアラインメント要件について語られています。コンパイラーはデータへの効率的なアクセスを可能にするために正しいパディングとオフセットを追加することを知っているので、それを心配する必要はありません。

唯一の例外は、ほとんどのコンパイラで手作業でアライメントを確保する必要があるSIMD命令で作業する場合です。それが正しい場合

第二に、そしてある は、8バイト境界上のデータ構造体を整列させるべきです。しかし私は 人がこれらのプロセッサの代わりに4バイトのアラインメント を使用しているのを見ました。

どのように違いがあるかわかりません。 CPUは、これらの4バイトを含む64ビットブロックの読み取りを発行するだけです。つまり、要求されたデータの前に4バイト余分になるか、それ以降に余分なバイトが得られます。しかし、どちらの場合も、1回の読み込みだけが必要です。 32ビット幅のデータの32ビットアライメントは、64ビット境界を越えないようにします。

+0

4バイトが1つの64ビットチャンクにまたがる場合はありません。 –

+0

4バイトの境界線で整列されているとどうなりますか? – jalf

+5

私はこの単純な推論を逃したとは思えません。同じパフォーマンスを4バイトで達成すると、8バイトのアライメントで4バイトの余分なバイトを無駄にするのはなぜですか? Jalfに感謝します。あなたは理にかなう。 –

6

物理バスは広い64ビットである... 8の倍数 - しかし、考慮すべき2つの要因があります>はい

  1. いくつかのx86命令セットは、バイトがアドレス指定されます。いくつかは32ビットアライメントです(そのため、4バイトのものがあります)。しかし、(コア)命令は64ビットで整列されていません。 CPUは、整列していないデータアクセスを処理できます。
  2. パフォーマンスを気にする人は、メインメモリではなくキャッシュラインについて考える必要があります。キャッシュラインははるかに広いです。
+0

私は分かりません。 Pentiumのようなプロセッサはアドレスバス上に8の倍数しか置かないことに同意します。次に、4バイトの配置は問題ないと言います。さて、アドレス0x000044444を考えてみましょう。 4バイトで整列されていますが、プロセッサは8の倍数ではないため、このアドレスをアドレス・ラインに出力することはありません。したがって、このアドレスのメモリをフェッチするには2回のフェッチが必要です。どのように4バイト整列が正当化されますか? –

+2

なぜ2つのフェッチが必要ですか?単に0x000044440から0x000044447までのすべてのデータを要求し、0x000044444-0x000044447に興味があるので、何が問題なのですか? – jalf

+0

なぜ命令のアライメントについて話しているのか、それは意味をなさない。 NOPとの境界への命令の埋め込みは何も達成しない。 –

0

ランダムアクセスの場合、データの位置がずれることがない限り(境界を越えるなど)、私はそれほど重要ではないと考えています。データ内の正しいアドレスとオフセットは、ハードウェア内の単純なAND構造で見つけることができます。 1つの読み取りアクセスで1つの値を取得するには不十分な場合は遅くなります。そのため、コンパイラは通常、小さな値(バイトなど)を特定のオフセットに配置する必要がないため、一緒に配置します。短絡は偶数アドレス、32ビットの4バイトアドレス、64ビットの8バイトアドレスでなければなりません。

キャッシングがインボリュートでリニアなデータアクセスの場合は、状況が異なることに注意してください。

2

8バイトのアライメントに変更するとABIの変更になり、限界性能の向上は問題にならないため、そうすることで正当化されます。

誰かが既に言ったように、キャッシュラインは重要です。実際のメモリバス上のすべてのアクセスは、キャッシュライン(x86、IIRC上の64バイト)に関するものです。すでに述べた「すべてのプログラマがメモリについて知っておく必要がある」ドキュメントを参照してください。したがって、実際のメモリトラフィックは64バイトに整列します。

1

あなたが参照する64ビットのバスは、キャッシュに供給されます。 CPUとして、常にキャッシュライン全体を読み書きします。キャッシュラインのサイズは常に8の倍数であり、その物理アドレスは実際に8バイトのオフセットで整列される。

キャッシュ間転送は外部データバスを使用しないため、そのバスの幅は関係ありません。

関連する問題