4

データ アライメントの理由に対する通常の答えは、より効率的にアクセスし、CPU の設計を簡素化することです。

関連する質問とその回答はこちら. そして別のソースはこちらです。しかし、どちらも私の質問を解決しません。

CPU のアクセス粒度が 4 バイトであるとします。つまり、CPU は一度に 4 バイトを読み取ります。上記の資料は両方とも、アドレス 0x1 などの位置合わせされていないデータにアクセスする場合、CPU は 2 つのアクセスを行う必要があることを示しています (アドレス 0x0、0x1、0x2、および 0x3 から 1 回、アドレス 0x4、0x5、0x6、および 0x7 から 1 回)。そして結果を結合します。理由がわかりません。アドレス 0x1 へのアクセスを発行したときに、CPU が 0x1、0x2、0x3、0x4 からデータを読み取れないのはなぜですか。パフォーマンスが低下したり、回路が複雑になることはありません。

前もって感謝します!

4

4 に答える 4

13

パフォーマンスが低下したり、回路が複雑になることはありません。

さらなる理解を本当に妨げているのは、私たちが事実として受け入れる誤った仮定です。

他の質問でのあなたのコメントは、はるかに適切な表現を使用していました(「劣化するとは思わない」...)

メモリ アーキテクチャでは、帯域幅を最大化するために多くのメモリ チップを並列に使用していると考えましたか? また、特定のデータ項目が 1 つのチップにしか含まれていないため、たまたま最も便利なチップを読み取って、必要なデータが含まれていると期待することはできません。

現在、CPU とメモリは、ビット 0 ~ 7 がチップ 0 のみに、8 ~ 15 がチップ 1 に、16 ~ 23 がチップ 2 に、24 ~ 31 がチップ 3 に、それぞれ配線されるように配線できます。すべての整数 N について、メモリ位置 4N はチップ 0 に格納され、4N+1 はチップ 1 に格納されます。これは、これらの各チップの N 番目のバイトです。

各メモリチップの各オフセットに格納されているメモリアドレスを見てみましょう

メモリチップ 0 1 2 3
オフセット

    0 0 1 2 3
    1 4 5 6 7
    2 8 9 10 11
    N 4N 4N+1 4N+2 4N+3


したがって、メモリ バイト 0 ~ 3、N=0 からロードすると、各チップはその内部バイト 0 を報告し、ビットはすべて適切な場所に配置され、すべてがうまくいきます。

では、メモリ位置 1 から単語を読み込もうとするとどうなるでしょうか?

まず、その方法を見てみましょう。メモリ チップ 1 ~ 3 のオフセット 0 に格納されている最初のメモリ バイト 1 ~ 3 は、最終的にビット 8 ~ 31 になります。これは、ビット 0 ~ 23 に配置するように要求したにもかかわらず、これらのメモリ チップが接続されている場所だからです。CPU は、論理左シフトに使用されるのと同じ回路を使用して、それらを内部でスウィズルできるため、これは大したことではありません。次に、オフセット 1 でメモリ チップ 0 に格納されている次のトランザクション メモリ バイト 4 がビット 0 ~ 7 に読み込まれ、必要な場所にビット 24 ~ 31 にスウィズルされます。

ここで何かに注意してください。要求した単語はオフセットに分割され、最初のメモリ トランザクションは 3 つのチップのオフセット 0 から読み取られ、2 番目のメモリ トランザクションは他のチップのオフセット 1 から読み取られます。ここに問題があります。メモリ チップにオフセットを伝えて正しいデータを送り返す必要があります。オフセットは最大 40 ビット幅で、信号は非常に高速です。現在、すべてのメモリ チップに接続するオフセット信号のセットは 1 つしかありません。アライメントされていないメモリ アクセスに対して 1 つのトランザクションを実行するには、各メモリ チップに対して実行する独立したオフセット (アドレス バス BTW と呼ばれます) が必要です。64 ビット プロセッサの場合、アドレス バスを 1 つから 8 つに変更すると、ほぼ 300 本のピンが増加します。CPU が 700 ピンから 1300 ピンを使用する世界では、これはほとんどとは言えません」

わかりました。それほど悪くはありません。一度にアドレス バスに出力できるオフセットは最大で 2 つまでであり、一方は常に他方に 1 を加えた値になるからです。したがって、各メモリ チップへの 1 本の余分なワイヤを使用して、実際には (アドレス バスにリストされているオフセットを読み取る) または (次のオフセットを読み取る) のいずれかを実行できます。これは 2 つの状態です。しかし今では、各メモリ チップに追加の加算器があるため、実際にメモリ アクセスを行う前にオフセットを計算する必要があり、メモリの最大クロック レートが遅くなります。つまり、アライメントされていないアクセスを高速化するには、アライメントされたアクセスが遅くなります。アクセスの 99.99% を揃えることができるため、これは純損失です。

そのため、アライメントされていないアクセスは 2 つのステップに分割されます。アドレス バスは関連するすべてのバイトで共有されるためです。これは実際には単純化したものです。オフセットが異なると、関連するキャッシュ ラインも異なるため、CPU コア間の 2 倍の通信を処理するには、すべてのキャッシュ コヒーレンシ ロジックを 2 倍にする必要があります。

于 2010-10-11T04:47:21.497 に答える
0

あなたの質問への答えは質問自体にあります。

CPUのアクセス粒度は4バイトです。したがって、4バイトのチャンクでのみデータを丸呑みにすることができます。

アドレス0x0にアクセスした場合、CPUは0x0から0x3までの4バイトを提供します。

アドレスからデータにアクセスするための命令を発行すると、CPUはそれを(すなわち)0x1で始まる4バイトのデータの要求として受け取ります。これは、基本的にCPUの粒度のため、他の方法で解釈することはできません。したがって、CPUは&(ergo、2アクセス)からのデータを丸呑み し、最終結果としてそれらのデータをまとめます。0x10x1 to 0x40x0 to 0x30x4 to 0x70x1 to 0x4

于 2010-10-11T04:08:49.767 に答える
0

最初のバイトが 0x0 ではなく 0x1 の左側に位置合わせされていない 4 バイトのアドレス指定は、ワード境界で開始せず、次の隣接するワードにスピルオーバーすることを意味します。最初のアクセスは 3 バイトからワード境界 (32 ビット ワードを想定) を取得し、次に 2 番目のアクセスはメモリ アドレッシング実装の 4 バイト 32 ビット ワードを完了するモードでバイト 0x4 を取得します。オブジェクト コードまたはアセンブラは、プログラマに対して透過的に 2 番目のアクセスと連結を効果的に実行します。通常は 4 バイト単位で、可能な場合はワード境界を維持するのが最善です。

于 2010-11-29T17:14:17.317 に答える
0

私の意見では、それは非常に単純化された仮定です。回路には、メモリの特定のビットが読み取られるようにするために、パイプリングとキャッシュの最適化の多くの層が含まれる場合があります。また、メモリの読み取りはメモリ サブシステムに委譲されます。メモリ サブシステムは、パフォーマンスと設計の複雑さが桁違いに異なるコンポーネントから構築され、思い通りに読み取ることができます。

ただし、私は CPU やメモリの設計者ではないので、くだらない話をしている可能性があるという警告を追加します。

于 2010-10-11T03:55:53.457 に答える