問題タブ [memory-alignment]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - 厳密なエイリアシングとアラインメントを壊さない C のメッセージ ディスパッチ システム
私は、互いにメッセージを送信する複数のタスクで構成される組み込み制御システムを C で作成しています (かなり一般的なイディオムだと思います!)。
- きちんとしている
- ジェネリックです
- 比較的効率的です
- 最も重要なこと:プラットフォームに依存しない (具体的には、厳密なエイリアスやアライメントの問題に違反しない)
概念的には、各メッセージ タイプを個別の構造体定義として表現したいと思います。また、次の関数 (簡略化) を備えたシステムが必要です。
ここで、aqueue_t
はノードのリンク リストで構成され、それぞれにchar buf[MAX_SIZE]
フィールドがあります。私が使用しているシステムにはmalloc()
実装がないため、空きノードのグローバル プールと、次のいずれかが必要になります (認識された問題は太字で示されています)。
sendMsg()
memcpy
空きノードのバッファへの受信メッセージの処理を行います。
私の理解では、呼び出し元が戻り値dequeueMsg()
をさらに処理しない限り、これにはアライメントの問題が発生します。memcpy
- または、呼び出し元 (送信者) が適切な型へのポインターにキャストする次の空きノードの
void *getFreeBuffer()
を返す関数があります。私の理解では、これには途中でアライメントの問題があり、途中でアライメントの問題を回避するためにまだ後が必要です.buf[]
memcpy
dequeueMsg()
- またはノードのバッファ
queue_t
を (eg) として再定義しuint32_t buf[MAX_SIZE]
ます。
私の理解では、これは厳密なエイリアシングに違反しており、プラットフォームに依存しません。
私が見ることができる他の唯一のオプションは、すべてのメッセージタイプの結合を とともに作成することですがchar buf[MAX_SIZE]
、これを「きれい」とは見なしません!
だから私の質問は、どうすればこれを適切に行うことができるのでしょうか?
winapi - アトミック x86 命令と MS の InterlockedCompareExchange ドキュメントのアライメント要件は?
Microsoft は、InterlockedCompareExchange
アトミック コンペア アンド スワップ操作を実行するための機能を提供しています。組み込みもあります。_InterlockedCompareExchange
x86 では、これらはlock cmpxchg
命令を使用して実装されます。
ただし、これら 3 つのアプローチに関するドキュメントを読んでみると、整合要件については一致していないようです。
Intel のリファレンス マニュアルには、アラインメントについては何も記載されていません (アラインメント チェックが有効で、アラインされていないメモリ参照が行われた場合、例外が生成されること以外は)
接頭辞も調べましたがlock
、具体的には次のように述べています
LOCK プレフィックスの整合性は、メモリ フィールドのアラインメントの影響を受けません。
(私のものを強調)
そのため、インテルはアライメントは無関係だと言っているようです。操作は何があってもアトミックになります。
_InterlockedCompareExchange
組み込みのドキュメントにもアラインメントについては何も記載されていませんが、関数InterlockedCompareExchange
には次のように記載されています
この関数のパラメーターは、32 ビット境界に揃える必要があります。そうしないと、関数はマルチプロセッサ x86 システムおよび非 x86 システムで予期しない動作をします。
それで、何が得られますか?命令が使用できないInterlockedCompareExchange
486 より前の CPU でも関数が機能することを確認するためだけのアライメント要件はありますか? cmpxchg
上記の情報に基づいている可能性が高いようですが、信頼する前に確認したいと思います。:)
それとも、原子性を保証するために ISA でアラインメントが必要なのですか? Intel のリファレンス マニュアルの間違った場所を探しているだけですか?
pointers - メモリ(sbrk)ポインタアクセスでの16バイト整列シフト
私はsbrkを使用してかなり基本的なメモリアロケータを作成しました。私はメモリのチャンク、たとえば65kを要求し、動的メモリを要求する変数の必要に応じてそれを切り分けます。65kブロックに追加してメモリを解放します。65kブロックは、ユニオンsizeof(16バイト)から派生します。次に、ブロックを16バイトの境界に沿って整列させます。しかし、私は異常な行動をとっています。
データ構造を割り当ててデータ構造にデータを入力し始めると、メモリへのアクセスは正常に表示されます。関数呼び出しの1つで、グローバル構造のメンバー変数へのポインターを渡しますが、ポインター引数のアドレスは直接マップされません。そのメンバーのアドレス。
たとえば、この特定のメンバーの実際のアドレスはたまたま0x100313d50ですが、特定の機能(特別なことは何もありません)を実行すると、メンバーのアドレスは0x100313d70として表されます。デバッガー内で実際のアドレスを照会できますが、これが現れる関数内では正しく表示されます。これも最初にアクセスされるメンバーではなく、3番目であるため、2回前のメモリアクセスで問題ありませんが、3回目のアクセス中に、この異常なシフトが見られます。
ずれたブロックを介してこのメモリにアクセスしている可能性はありますか?可能ですが、SIGBUS例外がスローされることを期待しています(SPARCチップ)。-memalign = 16sを使用してコンパイルしているので、ミスアライメントをトラップして修正するのではなく、SIGBUSを使用する必要があります。
私のすべての構造体は16バイトの倍数で埋められています:sizeof(structure)%16 =0。このタイプの動作を経験した人はいますか?一般的に言って、どんな種類のもの/もの/など。ポインタがメモリアドレスを誤って表現する可能性がありますか?
乾杯、トレーシー。
Solaris 10、SunStudio-12、最新のSPARCプロセッサ上のC言語(これが役立つ場合)。
c - アラインされていないメモリアクセスは常にバスエラーを引き起こしますか?
ウィキペディアのページのセグメンテーション違反によると、バスエラーはアラインされていないメモリアクセスによって引き起こされる可能性があります。この記事では、バスエラーをトリガーする方法の例を示しています。この例では、バスエラーを確認するためにアライメントチェックを有効にする必要があります。このようなアライメントチェックを無効にするとどうなりますか?
プログラムは正常に動作しているようです。私はプログラムがアラインされていないメモリに頻繁にアクセスし、それはかなりの数の人々によって使用されていますが、バスエラーやその他の奇妙な結果を私に報告する人は誰もいません。アラインメントチェックを無効にした場合、アラインされていないメモリの副作用は何ですか?
プラットフォーム: x86 / x86-64に取り組んでいます。また、Macで「gcc-arch ppc」を使用してプログラムをコンパイルしてみましたが、正常に動作します。
c++ - キャッシュ ラインの配置 (記事の説明が必要)
最近、自分のアプリケーションで false-sharing と思われる問題に遭遇したので、データをキャッシュラインに合わせる方法に関するSutter の記事を調べました。彼は次の C++ コードを提案しています。
CACHE_LINE_SIZE > sizeof(T)
が true の場合、これがどのように機能するかがわかります。構造体cache_line_storage
は、メモリの 1 つの完全なキャッシュ ラインを占有するだけです。ただし、が 1 つのキャッシュ ラインよりも大きい場合は、結果の構造体のサイズがキャッシュ ライン サイズの整数倍になるようにsizeof(T)
、データをバイト単位でパディングする必要があると思います。CACHE_LINE_SIZE - T % CACHE_LINE_SIZE
私の理解の何が問題になっていますか?なぜ 1 バイトのパディングで十分なのですか?
delphi - Delphi ルーチンの 16 バイト コード アラインメントを確保するにはどうすればよいですか?
バックグラウンド:
主に重い計算用に、最適化された Delphi/BASM ルーチンのユニットがあります。これらのルーチンの一部には内部ループが含まれており、ループの開始が DQWORD (16 バイト) 境界に揃えられている場合、大幅な高速化を実現できます。ルーチンのエントリ ポイントでの位置合わせがわかっている場合は、問題のループが目的どおりに位置合わせされていることを確認できます。
私の知る限り、Delphi コンパイラはプロシージャ/関数を DWORD 境界に揃えます。たとえば、ユニットに関数を追加すると、後続の関数の配置が変更される場合があります。ただし、ルーチンの末尾を 16 の倍数になるようにパディングする限り、最初のルーチンの配置に応じて、後続のルーチンも同様に配置されるか、または配置がずれることを保証できます。したがって、重要なルーチンをユニットの実装セクションの先頭に配置し、それらの前に少しのパディング コードを配置して、最初のプロシージャが DQWORD でアラインされるようにしました。
これは以下のようになります。
これは少し首の痛みですが、必要に応じてこの種のことを機能させることができます. 問題は、そのようなユニットを別のプロジェクトで使用したり、同じプロジェクト内の他のユニットに変更を加えたりすると、__PadFirstProcTo16
それ自体の配置が崩れる可能性があることです。同様に、同じプロジェクトを異なるコンパイラ バージョン (D2009 と D2010 など) で再コンパイルすると、通常は整合が崩れます。そのため、私が見つけたこの種のことを行う唯一の方法は、プロジェクトの残りの部分がすべて最終的な形になったときに行う最後の作業として、手動で行うことでした。
質問1:
(少なくともいくつかの特定の) ルーチンが DQWORD に揃えられていることを保証するという望ましい効果を達成する他の方法はありますか?
質問2:
コンパイラのコードの配置に影響を与える正確な要因はどれですか?また、(どのように)そのような特定の知識を使用して、ここで概説されている問題を克服できますか?
この質問のために、「コードのアライメントについて心配する必要はありません/関連するおそらく小さな速度の利点」は許容できる答えではないと仮定します。
c++ - SSE2-16バイトにアラインされたメモリの動的割り当て
編集:
これは私が以前に経験した本当のバグであり、 MichaelBurrが提案したように_mm_malloc
ステートメントを変更することによって以下に再現しました。
SO.exeの0x00415116で未処理の例外:0xC0000005:アクセス違反の読み取り場所0xffffffff。
ラインでlabel: movdqa xmm0, xmmword ptr [t1+eax]
私は動的に割り当てようとしていますt1
、t2
そしてこのチュートリアルによれば、私は以下を使用しました_mm_malloc
:
c - C GCC での関数の配置
「aligned(16)」属性を使用して、関数を 16 バイト境界にバイト アラインしようとしています。私は次のことをしました: void __attribute__((aligned(16))) function() { }
(ソース: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html )
しかし、コンパイルすると (gcc foo.c ; makefile やリンカー スクリプトは使用されません)、次のエラーが発生します。
FOO.c:99: エラー: '関数' にアラインメントが指定されていない可能性があります
4、8、32などにも合わせてみましたが、エラーは同じままです。これは、powerpc ベースのプロセッサの割り込みサービス ルーチンを調整するために必要です。そうする正しい方法は何ですか?
performance - データ構造の調整がパフォーマンスにとって重要なのはなぜですか?
コンパイラがメンバーを整列させるためにデータ構造にパディングを追加する理由について、誰かが私に短くてもっともらしい説明を教えてもらえますか?CPUがより効率的にデータにアクセスできるようにするために行われていることは知っていますが、なぜそうなのかわかりません。
そして、これがCPUにのみ関連している場合、なぜLinuxではダブル4バイトが整列され、Windowsでは8バイトが整列されるのでしょうか。