5

重複の可能性:
Qt、GCC、SSE、およびスタック アライメント

シミュレーターを TinyPTC から WxWidgets に変換しています。一部のグラフィックス ルーチンは、SSE 組み込み関数で最適化されています。GUI の初期化中に、初期状態が 1 回レンダリングされ、すべての SSE ルーチンが完全に機能します。ただし、後でイベント ハンドラーから呼び出すと、SIGSEGV が返されます。

最初は、これらはいくつかの奇妙な配置の問題だと思っていましたが、次の場合にも発生します。

__m128i zero = _mm_setzero_si128();

SSE ルーチンを最適化されていないコードに置き換えると、すべて正常に動作します。

イベント処理は、初期化とは別のスレッドで行われると思います。異なるスレッドから SSE を使用する場合に注意することはありますか? 他に何がこの動作を引き起こす可能性がありますか?


SIGSEGV はmovdqa %xmm0, -40(%ebp)命令で発生します (いくつかあります)。でコンパイルすると-O1movdqa命令は完全に最適化され、プログラムは正常に実行されます。コメントですでに指摘されているように、結局のところ、スタックとのアライメントの問題のようです。

CodeLite がコンパイル用に生成するコマンドは次のとおりです。

g++ -c "x:/some/folder/sse.cpp" -g -O1 -Wall -std=gnu++0x -msse3
-mthreads -DHAVE_W32API_H -D__WXMSW__ -D__WXDEBUG__ -D_UNICODE
-ID:\CodeLite\wxWidgets\lib\gcc_dll\mswud -ID:\CodeLite\wxWidgets\include
-DWXUSINGDLL -Wno-ctor-dtor-privacy -pipe -fmessage-length=0 -o ./Debug/sse.o -I.

何か珍しいことはありますか?WxWidgets が配置設定をどこかで変更する可能性はありますか?

4

3 に答える 3

4

スタックポインタがずれている可能性があります。SSE命令では、すべてのメモリ位置が16バイトにアラインされている必要があります。この問題は_mm_setzero_si128、定数をSSEレジスタにロードするだけの命令ではなく、そのレジスタをスタックのメモリに格納するためにコンパイラが生成した命令で発生します。

まず、古いバージョンのGCCを使用していないことを確認します(古いバージョンでは、SSEとのスタックアライメントに問題がありました)。次に、-mstackrealignその変換ユニットのオプションも追加してみてください。これにより、関数エントリでスタックが16バイトの整列に強制的に再整列されます(これにより、実行時のコストが非常に小さくなります)。

命令および例外を生成する可能性のある正確な条件の詳細については、インテル・アーキテクチャー・ソフトウェア開発者マニュアルの第2B巻4-67ページを参照してください。movdqa

于 2012-07-26T15:26:04.670 に答える
0

私の知る限り、wxWidgets イベント処理はメイン スレッド (GUI スレッド) で実行されます。デバッガで実行すると、これを確認できるはずです。デバッガーは、セグメント違反が発生した場所に関するヒントも提供する必要があります。

于 2012-07-26T13:54:33.633 に答える
0

SSE ルーチンにバグがある可能性があります。SSE 命令は、より大きなブロックにデータを書き込みます。SSE で配列をゼロにするときに、配列の末尾をオーバーランしている可能性があります。たとえば、ゼロ化された配列が 8 バイトの倍数でないかどうかを確認します。そのため、最適化されていない命令を使用して、配列の奇数端を実行することをお勧めします。

于 2012-07-26T14:00:08.643 に答える