インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス
インテル® Cilk™ Plus は古い機能 (非推奨) です。代わりに、OpenMP* またはインテル® TBB を使用してください。詳細は、「インテル® Cilk™ Plus の代わりに OpenMP* またはインテル® TBB を使用するためのアプリケーションの移行」を参照してください。
Microsoft* Foundation Class (MFC) ライブラリーは、クラスラッパーからオブジェクトの GDI ハンドラーをマップするスレッド・ローカル・ストレージに依存します。インテル® Cilk™ Plus のストランドは、どの OS スレッドでも実行できるわけではないため、インテル® Cilk™ Plus を使用する並列コードでは MFC 関数を安全に呼び出すことができません。
通常、MFC ベースのアプリケーションで計算集約的なタスクを実行する方法は 2 つあります。
ユーザー・インターフェイス (UI) スレッドは、計算集約的なタスクを実行する演算スレッドを作成します。演算スレッドは UI スレッドにメッセージを送信して、UI スレッドが UI を更新します。このため、UI スレッドは計算集約的なタスクの実行から解放され、UI 要求に対応できます。
UI スレッドが計算集約的なコードを実行し、直接 UI を更新します。UI 要求は、ときどき "メッセージポンプ" を実行することで処理します。
ランタイムシステムは OS スレッドを切り替えることができるため、インテル® Cilk™ Plus コードはスレッド・ローカル・ストレージに依存する MFC などのコードと分離する必要があります。
MFC プログラムに演算スレッドを追加するには、次の操作を実行します。
OS 機能 (_beginthreadex や AfxBeginThread) を使用して演算スレッドを作成します。インテル® Cilk™ Plus に変換する C++ コードはすべてこのスレッドで実行する必要があります。演算スレッドによりメイン (UI) スレッドは計算集約的なタスクから解放され、メッセージポンプを実行して、ウィンドウメッセージの処理と UI の更新を行うことができます。
UI ウィンドウのハンドル (HWND) を演算スレッドに渡します。UI の更新が必要になると、演算スレッドは PostMessage を呼び出して UI スレッドにメッセージを送信します。PostMessage はメッセージをマーシャリングして、ウィンドウハンドルを作成したスレッドに関連付けられているメッセージキューに追加します。SendMessage は使用しないでください。SendMessage は、正しい (UI) スレッドではない現在実行中のスレッドで実行されます。
C++ プログラムをテストして、ロジックとスレッド管理が正しいことを確認します。
演算スレッドのロジックにインテル® Cilk™ Plus 構造を追加します。
終了する前に、メイン (UI) スレッドは WaitForSingleObject() を使用して、演算スレッドが完了するのを待機しなければなりません。
製品に含まれる QuickDemo サンプルプログラムは、インテル® Cilk™ Plus アプリケーションで MFC を使用する例を示します。
その他の推奨事項:
メイン UI スレッドが演算スレッドを作成する場合は、演算スレッドの終了を待機すべきではありません。演算スレッドを作成する関数は、メッセージポンプが実行できるように戻る必要があります。
演算スレッドに渡されるデータはすべてスタックに割り当てられているデータであってはなりません。スタックに割り当てられているデータが渡されると、演算スレッドを作成する関数が戻ったときに、スタックデータが解放されてしまいます。
演算スレッドに渡されるデータブロックは、処理が終了し UI に完了メッセージを送信する直前に、演算スレッドによって解放されなければなりません。
演算スレッドを作成する主な理由は、インテル® Cilk™ Plus コードで MFC のスレッドローカル変数を使用しないようにするためなので、CWnd::PostMessage の代わりに PostMessage 関数を使用します。
インテル® Cilk™ Plus 構造を使用する (短い) 計算はブラックボックス化され、メッセージポンプやほかのスレッドと通信しない限り、UI スレッドから直接呼び出すことができます。そのため、非インタラクティブな関数を、それらがインテル® Cilk™ Plus を使用しているかどうかに関わらず、呼び出すことが可能です。