アラインされたメモリアクセスとアンアラインされたメモリアクセス?

StackOverflow https://stackoverflow.com/questions/1063809

質問

アライメントされたメモリアクセスとアンアライメントされたメモリアクセスの違いは何ですか?

TMS320C64x DSP で作業しており、組み込み関数 (アセンブリ命令用の C 関数) を使用したいのですが、

ushort & _amem2(void *ptr);
ushort & _mem2(void *ptr);

どこ _amem2 2 バイトのアライメントされたアクセスを実行し、 _mem2 非整列アクセスを行います。

いつどれを使えばいいのでしょうか?

役に立ちましたか?

解決

整列メモリアクセス(整数として)ポインタアライメントと呼ばれるタイプ固有の値の倍数であることを意味します。アラインメントは、タイプがなければならない、またはCPU上で(例えば、パフォーマンス上の理由のために)格納されるべき天然アドレス倍です。例えば、CPUは、すべて2バイトのロードまたはストアが2の倍数のアドレスを介して行われていることを必要とするかもしれません。小さなプリミティブ型(4バイト未満)ため、位置合わせは、ほとんどのタイプの大きさです。構造体のために、位置合わせは、通常、任意のメンバの最大アラインメントです。

この Cコンパイラは、常にあなたが「正しい」アライメントを満たすアドレスで宣言した変数を置きます。だから、ポイントPTR場合は、例えばしますuint16_t変数は、それが整列され、あなたは_amem2使用することができます。あなたは、例えばアクセスしている場合にのみ_mem2使用する必要がありますパックされたバイト配列は、文字列の途中にI / O、またはバイトを介して受信します。

他のヒント

数バイトごとの「言葉」で多くのコンピュータ・アーキテクチャストアメモリ。例えば、Intelの32ビットアーキテクチャは、32ビット、4バイトのそれぞれの単語を記憶します。メモリはしかし、単一バイトレベルで取り組まれています。したがって、アドレスは、それがないという意味、ワード境界から始まる、または「非整列」を意味し、「整列」することができます。

特定のアーキテクチャでは、特定のメモリ動作が遅くなることがあり、あるいは完全にアラインされていないアドレスで許可されていない。

あなたのアドレスが正しいアドレスに整列されている知っていれば、

だから、あなたはスピードのために、)(_amem2使用することができます。そうでなければ、あなたは)(_mem2使用する必要があります。

アライメントされたアドレスとは、問題のアクセス サイズの倍数であるアドレスです。

  • 4 の倍数のアドレス上の 4 バイト ワードへのアクセスはアライメントされます。
  • アドレス(例えば)3から4バイトのアクセスはアンアラインアクセスとなります

可能性が非常に高いです。 _mem2 アライメントされていないアクセスでも機能する関数は、コード内で正しいアライメントを機能させるにはあまり最適ではありません。これは、 _mem2 関数はその関数よりもコストが高くなる可能性があります _amem2 バージョン。

したがって、パフォーマンスが必要な場合 (特にアクセス遅延が高いことがわかっている場合)、いつアライメントされたアクセスを使用できるかを特定することが賢明です。の _amem2 はまさにこの目的のために存在します。アクセスが調整されていることがわかっている場合にパフォーマンスを提供するためです。

2 バイト アクセスに関しては、アライメントされた操作を識別するのは非常に簡単です。
操作のすべてのアクセス アドレスが「偶数」(つまり、LSB が 0) の場合、2 バイト アライメントになります。これは次のように簡単に確認できます。

if (address & 1) // is true
    /* we have an odd address; not aligned */
else
    /* we have an even address; its aligned to 2-bytes */

私は、これは選択された解答と古い質問です知っているが、誰もが揃っていて、アライメントが合わないメモリアクセスの違いは何かに対する答えを説明参照didntの...

これは、DRAMやSRAM、フラッシュ、または他う。それは、特定のSRAMは広くて深い行一定数の固定のビット数から構築されたビットから構築されている簡単な例として、SRAMを取ります。 32ビット幅で言うとLETS /いくつかの多くの行深います。

私はこのSRAMには0x0000に対処する32ビットの書き込みを行う場合は、単に単一の書き込みサイクルを行うことができ、このSRAMの周りにメモリコントローラは0行に

Iが許容されると仮定すると、このSRAMには0x0001に対処するための32ビットの書き込みを行う場合、コントローラ一保存、バイトのうち3つを変更し、行0の読み出しを行う必要があります、そしてそれは0行への書き込み、その後、行1が見出される他の三つを残して、1つのバイトを変更し、その裏面を読み書き。これは変更またはシステムのエンディアンに関係していない取得バイトます。

前者は整列され、後者整列されていない、明らかにパフォーマンスの違いに加えて4つのメモリ・サイクルを行い、バイトレーンをマージできるようにするには、余分なロジックを必要とします。

私は、アドレス0x0000から32ビットを読み取るために、行0の単一読み取った場合、

、行わ。しかし、0x0001のから読んで、私は、2つのROW0とROW1を読み取り、システム設計に応じて、単にプロセッサに戻って代わりに1の可能性の2つのバスクロックをこれらの64ビットを送信しなければなりません。 32ビットが1つのバスサイクル中にデータ・バス上に並ぶようにまたはメモリコントローラは、余分なロジックを有している。

16ビットの読み取りバックこれらの32ビットを送信し、唯一ROW0から読み取られるであろうと、システム/プロセッサ設計に基づくことができ0000、は0x0001と0×0002から読み出し少し優れているとプロセッサがそれらの抽出物またはそれらをシフトメモリコントローラ持ってdoesntのプロセッサが周りを回転するので、彼らは、特定のバイトレーンに着地するように。どちらか一方ではなく、両方の場合があります。あなたのバイトの1つとして、行0とROW1を読まなければならない上に、各ている等0x0003から読み出しもののどちらか(抽出またはメモリコントローラは、1つの32ビット・バスの応答にビットを合成するためのバックプロセッサの64ビットを送信しますプロセッサとメモリコントローラとの間でバスを想定する)これらの実施例のために32ビット幅である。

16ビット書き込み、常にこの例SRAM、アドレス0x0000に少なくとも一つのリードモディファイライトで終わるのに、は0x0001と0x0002は、リードは2つのバイトを変更し、ライトバックROW0。アドレス0x0003には、それぞれを1つのバイトを変更し、ライトバック2行を読み取ります。

8ビットだけそのバイトを含む1行を読み取る必要がある、1行のリードモディファイライトですけれども書き込みます。

整列していないようなARMV4 didntはあなたがトラップを無効にすることができ、その結果、それをあなたが上、重要ではない、現在の腕が整列していない許可を期待して、あなたがコントロールレジスタのビットを変更することができます上記の動作を与えるだろう好きで、その後されていませんが、非整列転送を中止します。 MIPSは、彼らが今何をするかわからない、許可しないために使用されます。 x86のは、68Kなど、許可されたメモリコントローラは、ほとんどの仕事をしなければならなかったかもしれません。

それを許可していけないデザインが明確にそれがプログラマにプログラマや簡単に上の余分な仕事ではないと言うかもしれないプログラマの他人の負担が何であるかを、いくつかが言うの性能と少ないロジックのためのものです。 8ビット変数を作成することにより、任意のメモリを節約しようとするが、先に行くと、32ビット・ワードまたは任意のレジスタの自然なサイズやバスがあるがやけどしないように改善することができますなぜ整列か、あなたも見ることができます。これは、いくつかのバイトの小さなコストであなたのパフォーマンスを助けるかもしれません。コンパイラは、32ビット・レジスタは8ビットの変数を模倣言うことができます作るために追加のマスキング、時には延長に署名する必要があります余分なコードは言うまでもありません。レジスタネイティブサイズを使用した場合には、これらの追加の命令が必要とされていません。あなたはまた、バス/メモリに広い場所を複数のものをパックすることができ、その後メートルにいくつかの余分な命令を使用し、それらを収集したり、書き込みに1つのメモリ・サイクルをくださいラムと命令の数の可能性洗浄原価計算ではない。

レジスタ間anipulate

私は、コンパイラは常にターゲットのデータを右に揃えることに同意するものといけない、それを打破する方法があります。ターゲットが整列していないサポートをdoesntの場合、あなたは障害をヒットします。コンパイラは常にそれが右の法的コードに基づいて、あなたが思い付くことができなかった場合、プログラマはこのことについて話をする必要がないだろう、それはパフォーマンスのためでない限り、この質問の理由はないだろう。あなたが整列するボイドPTRアドレスを制御したりないいけない場合、あなたは(MEM2を使用する必要があります)非整列アクセスのすべての時間か、NIKとしてPTRの値に基づいて、あなたのコードにされたif-then-elseを行う必要があります指摘した。 voidとして宣言することによって、Cコンパイラは正しく整列に対処する方法はありませんし、それを保証することが文句を言いません。あなたがするchar * PRTを取り、これらの機能にそれを養う場合、すべてのベットは右のどちらかMEM2()関数の中で、またはこれら二つの関数の外に埋葬余分なコードを追加することなく、それを取得して、コンパイラにオフになっています。 )(あなたの質問MEM2に書かれたように、唯一の正解である。

DRAMは、デスクトップ/ノートPCに使用されるが、64または72(ECC付き)になりやすいワイドビット、およびそれらへのすべてのアクセスが整列していると言います。メモリスティックは、実際には8ビット幅または16個のまたは32ビット幅のチップで構成されているにもかかわらず。メモリコントローラ(これは様々な理由のために携帯電話/タブレットで変化してもよい)および非整列又はバス幅よりも小さくても整列アクセス読み取り - 変更 - 書き込みが配られるように、理想的には少なくとも一つのキャッシュは、このドラムの前に座っています道速く、DRAMのアクセスがすべて揃っフルバス幅がアクセスされるキャッシュSRAMのあります。あなたがドラムの前で何のキャッシュを持っていないと、コントローラは全幅のために設計された個別のバイトレーンを点灯するために設計された場合には、最悪のパフォーマンス(8ビット幅のチップを想定)され、次にアクセスした場合、あなたは読み取りがモディファイ持っていけません-writesが、より複雑なコントローラ。 (デザインの1がある場合)、典型的なユースケースがキャッシュにある場合、それは各バイトレーン用のコントローラでその追加の仕事を持ってしても意味がないかもしれませんが、それだけで完全なバス幅サイズの転送を行う方法を知っていますまたはその倍数ます。

_mem2は、より一般的です。 PTRが整列されているかどうか、それは動作します。 _amem2はより厳密である:(おそらく若干より効率的であるが)、それは、ptrが整列されることを必要とします。あなたはptrが常に揃っていることを保証することができない限り_mem2使用します。

多くのプロセッサは、メモリアクセスのアラインメントの制限があります。アラインされていないアクセスは、例外、割り込み(例えば、ARM)を生成し、又は(例えば、x86の)だけ遅いいずれか

_mem2は、おそらく2つのバイトをフェッチし、それらのうちの16ビットUSHORTを作るためにシフト及びまたはビット単位の操作を使用してとして実装されます。

_amem2はおそらく、指定PTRから16ビットのUSHORTを読み込みます。

私は、具体的のTMS320C64xを知らないが、私は推測するだろう、それは16ビットのメモリをアクセスするためには、16ビットのアライメントを必要とします。あなたはptrが偶数アドレスであることを保証することができますときに、あなたは常にが、パフォーマンスの低下、および_mem2_amem2を使用することができます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top