私はここ数日、奇妙な問題に苦しんでいます。 GCC 4.8を使用していくつかのライブラリを作成し、それらの依存関係の一部を静的にリンクします。 log4cplusまたはブースト。これらのライブラリ用に、boost-pythonを使用してPythonバインディングを作成しました。
そのようなライブラリがTLSを使用するたびに(log4cplusが静的初期化で行うように、またはstdlibc ++が例外をスローするときに(初期化フェーズ中だけでなく)、すべてがセグメンテーションフォールトでクラッシュしました-そしてスレッドローカル変数のアドレスが0になるたびに。
再コンパイル、-fPICが使用されていることの確認、-tls-model = global-dynamicが使用されていることの確認などすべてを試しました。成功しませんでした。そして今日、これらのクラッシュの理由は、OpenMPをリンクする方法にあることがわかりました。これは、単に「-fopenmp」を使用する代わりに「-lgomp」を使用して行いました。これを変更したので、すべてが正常に機能します-クラッシュも何もありません。いいね!
しかし、私は本当に問題の原因が何であったかを知りたいです。では、OpenMPでリンクするこれら2つの可能性の違いは何ですか?
ここにCentOS5マシンがあり、GCC-4.8を/ opt/local/gcc48にインストールしました。また、/ opt/local/gcc48からのlibgompと、そこからのlibstdc ++(DL_DEBUG)が使用されたことも確認できます。中古)。
何か案は? Googleで何も見つかりませんでした-または間違ったキーワードを使用しました:)
OpenMPは、コードとその実行の間の仲介者です。各#pragma omp
ステートメントは、対応するOpenMPライブラリ関数への呼び出しに変換されます。これですべてです。マルチスレッドの実行(スレッドの起動、スレッドの結合と同期など)は、常にオペレーティングシステム(OS)によって処理されます。 OpenMPが行うのは、これらの低レベルのOS依存のスレッド呼び出しを、短くて甘いインターフェースで移植可能に処理することだけです。
-fopenmp
フラグは、GCCのOpenMP実装(gomp)を含む以上のことを行う高レベルのフラグです。このgompライブラリでは、OSのスレッド機能にアクセスするためにより多くのライブラリが必要になります。 POSIX準拠のOSでは、OpenMPは通常pthreadに基づいており、リンクする必要があります。一部のOSで動作するには、リアルタイム拡張ライブラリ(librt)が必要な場合もありますが、他のOSでは動作しません。ダイナミックリンクを使用する場合、すべてが自動的に検出されるはずですが、-static
を指定すると、Jakub Jelinek ここ で説明されている状況に陥ったと思います。しかし、最近では、-static
を使用すると、pthread(および必要に応じてrt)が自動的にリンクされるはずです。
依存関係をリンクする以外に、-fopenmp
フラグはいくつかのプラグマステートメント処理もアクティブにします。 GCCコード全体で( here および here として)、-fopenmp
フラグ(gompライブラリをリンクするだけではトリガーされない)がないことがわかります。複数のプラグマは、適切なOpenMP関数呼び出しに変換されません。いくつかのサンプルコードを試してみましたが、-lgomp
と-fopenmp
の両方で、同じライブラリにリンクする実行可能ファイルが生成されます。私の簡単な例の唯一の違いは、-fopenmp
には-lgomp
にはない記号があります:GOMP_parallel@@GOMP_4.0+
(code here )これは次の関数ですサンプルコードの#pragma omp parallel
によって要求されたフォークを実行する並列セクションを初期化します。したがって、-lgomp
バージョンは、プラグマをGCCのOpenMP実装への呼び出しに変換しませんでした。どちらも動作する実行可能ファイルを生成しましたが、この場合、-fopenmp
フラグのみが並列実行可能ファイルを生成しました。
まとめると、GCCがすべてのOpenMPプラグマを処理するには-fopenmp
が必要です。これがないと、並列セクションはスレッドをフォークしません。これは、内部コードが実行された前提条件によっては大混乱を引き起こす可能性があります。