11

ページ境界を越えてデータにアクセスする movdqu 命令で xmm レジスタをロードする簡単なテスト プログラムがあります (OS = Linux)。

次のページがマップされている場合、これは問題なく機能します。マップされていない場合は、SIGSEGV を取得しますが、これはおそらく予想どおりです。

ただし、これにより、アライメントされていないロードの有用性がかなり低下します。さらに、アラインされていないメモリ参照を可能にする SSE4.2 命令 (pcmpitri など) も、この動作を示すようです。

それはすべて問題ありません - pcmpistri を使用した strcmp の実装が多く、この問題にまったく対処していないように見えることを除いて - そして、これらの実装が失敗する原因となる簡単なテストケースを考案することができました。一方、一度にバイト単位の単純な strcmp 実装は、同じデータ レイアウトで問題なく動作します。

もう 1 つ注意してください。64 ビット Linux 用の GNU C ライブラリの実装には、より安全な方法で pcmpistri 命令を使用するように見える __strcmp_sse42 バリアントがあるようです。この strcmp の実装はかなり複雑ですが、ページ境界の問題を慎重に回避しようとしているようです。それが上で説明した問題によるものなのか、それともデータを調整してパフォーマンスを向上させようとしたことの単なる副作用なのかはわかりません。

とにかく、私が持っている質問は、主に、この問題についてどこで詳しく知ることができますか? 「movdqu クロス ページ境界」と入力して、考えられるすべてのバリアントを Google に入力しましたが、特に役立つものは見つかりませんでした。誰かが私にこれに関する詳細情報を教えてくれるなら、それは大歓迎です。

4

2 に答える 2

8

まず、マップされていないアドレスにアクセスしようとするアルゴリズムは、SegFault を引き起こします。AVX 以外のコード フローが 4 バイトのロードを使用してページの最後のバイトと「次のページ」の最初の 3 バイトにアクセスした場合、たまたまマップされていなかった場合も SegFault が発生します。いいえ?「問題」は、AVX(1/2/3) レジスタが「一般的な」レジスタよりもはるかに大きいため、安全でない (しかしそれを回避した) アルゴリズムがより大きなレジスタに自明に拡張された場合に捕まることにあると思います.

アラインされたロード (MOVDQA) は、それ自体のサイズ以上の境界を越えないため、この問題が発生することはありません。アライメントされていないロードには、この問題が発生する可能性があり (ご指摘のとおり)、「頻繁に」発生します。これは、命令がターゲット レジスタのフル サイズをロードするように定義されているためです。命令定義のオペランドの型を注意深く調べる必要があります。関心のあるデータの量は重要ではありません。命令が何を行うように定義されているかが重要です。

でも...

AVX1 (Sandybridge) は、movdqa や movdqu よりも低速ですが、マップされていないページに (アーキテクチャ的に) アクセスしない「マスクされた移動」機能を追加しました。 . これは、この問題に対処するためのものです。一般に、ロード/ストアのマスクされた部分 (AVX512 を参照) が IA でアクセス違反を引き起こすことはないようです。

(PCMPxSTRx の動作については残念です。おそらく、「文字列」オブジェクトに 15 バイトのパディングを追加できますか?)

于 2014-06-20T23:34:15.743 に答える
2

私が書いていたライブラリで同様の問題に直面したとき、非常に役立つ貢献者からいくつかの情報を得ました。

アイデアの核心は、16 バイトの読み取りを文字列の末尾に揃え、残りのバイトを先頭で処理することです。これが機能するのは、文字列の末尾がアクセス可能なページに存在する必要があり、16 バイトの切り捨てられた開始アドレスもアクセス可能なページに存在する必要があることが保証されているためです。

文字列を読み取らないため、保護されたページに迷い込む可能性はありません。

バイトの初期セットを処理するためにPCMPxSTRM、一致するバイトのビットマスクを返す関数を使用することにしました。次に、結果をシフトして、文字列の真の始まりの前に発生するマスク ビットを無視するだけです。

于 2015-05-17T14:41:12.493 に答える