アプリケーション (Win64、C++) をより非同期にすることで改善しています。私はコンカレンシー ランタイムを使用していますが、これまでのところうまく機能しています。
アプリケーションは基本的に、データを変換する多数の「ジョブ」を実行します。各ジョブの動作を追跡するために、特定のサブシステムには、ジョブが実行する特定の操作を追跡するためのコードが組み込まれています。以前は、現在実行中のジョブを表す単一のグローバル変数を使用して、呼び出しチェーン全体でコンテキスト情報を渡すことなく追跡情報を登録できました。各ジョブは、ConcRT を使用してジョブ自体を並列化することもできます。これはすべて非常にうまく機能します。
ただし、トップレベルのジョブを並行して実行できるように、アプリケーションをリファクタリングしています。各ジョブは ConcRT タスクとして実行されます。これは、追跡が必要なジョブを除くすべてのジョブでうまく機能します。
私が基本的に必要としているのは、いくつかのコンテキスト情報をタスクに関連付け、そのタスクによって生成された他のタスクにそのフローを持たせる方法です。基本的に、「タスクローカル」変数が必要です。
ConcRT では、ジョブが ConcRT を使用して他のジョブを生成する可能性があり、これらは任意の数のスレッドで実行されるため、単純にスレッド ローカルを使用してコンテキスト情報を格納することはできません。
私の現在のアプローチでは、起動時に多数の Scheduler インスタンスを作成し、そのジョブ専用のスケジューラで各ジョブを生成します。次に、このConcurrency::CurrentScheduler::Id()
関数を使用して、コンテキストを把握するためのキーとして使用できる整数 ID を取得できます。これは機能しますが、Concurrency::CurrentScheduler::Id()
in アセンブリを 1 回ステップ実行すると、複数の仮想関数呼び出しと安全性チェックが実行され、かなりのオーバーヘッドが追加されるため、ややひるみます。場合によっては料金。
だから - これを達成するためのより良い方法はありますか? 単一のコンテキスト ポインターを現在の Scheduler/SchedulerGroup/Task に関連付けることができるファーストクラスの TaskLocal/userdata メカニズムがあれば、それをほとんどオーバーヘッドなく取得できればよかったのにと思います。
ConcRT スレッドが新しいタスクを取得するたびに呼び出されるフックが理想的です。これにより、Scheduler/ScheduleGroup ID を取得してスレッド ローカルに格納し、アクセス オーバーヘッドを最小限に抑えることができます。残念ながら、そのようなフックを登録する方法が見当たらず、PPL/エージェント用のカスタム スケジューラ クラスを実装することもできないようです (この記事を参照してください)。