マルチスレッドアプリを書いています。
boost::interprocess クラスを使用していました (バージョン 1.36.0)
基本的に、私は作業が可能になったときに通知する必要があるワーカー スレッドを持っています。
「セマフォ」と「条件」の両方のアプローチを試しました。
どちらの場合も、ワーカー スレッドの CSwitch (コンテキスト スイッチ) は、1 秒あたり 600 回の切り替えなど、非常に高いように見えました。
私はコードを見て、(アトミックにミューテックスを使用して) フラグをチェックし、次に再試行する前にタイムスライスを生成するようです。
コードで WaitForSingleObject などを使用することを期待していました。
皮肉なことに、これはまさに私が「適切に」実行して Boost を使用することを決定する前に行っていた方法でした! (つまり、mutex を使用してフラグの状態を定期的にチェックします)。唯一の違いは、私のアプローチでは、チェックの間に 50 ミリ秒ほど寝ていたので、高い CSwitch の問題はありませんでした (そして、50 ミリ秒まで作業が開始されないことは問題ありません)。
いくつかの質問:
- この「高い」CSwitch 値は重要ですか?
- ブースト ライブラリがセマフォの代わりに CRITICAL_SECTIONS を使用していた場合、これは発生しますか (プロセス間の同期は気にしません - すべてのスレッドが同じプロセスにあります)。
- ブーストが WaitForSingleObject を使用していた場合、これは発生しますか?
- Boost ライブラリには、前述の Win32 待機メソッド (WaitForXXX) を使用する別のアプローチがありますが、これはこの CSwitch の問題に悩まされることはないと思います。
更新:これは疑似コード サンプルです。少し複雑になるため、実際のコードを追加することはできません。しかし、これは私がやっていることのほとんどです。これは、1 回限りの非同期アクティビティを実行するスレッドを開始するだけです。
注:これらは単なるイラストです。このサンプルには負荷がありません。たとえば、スレッドが「待機」に達する前に injectWork() を呼び出した場合、機能しません。ブーストの使い方を説明したかっただけです。
使用法は次のようなものです。
int main(int argc, char** args)
{
MyWorkerThread thread;
thread.startThread();
...
thread.injectWork("hello world");
}
これはブーストを使用した例です。
class MyWorkerThread
{
public:
/// Do work asynchronously
void injectWork(string blah)
{
this->blah = blah;
// Notify semaphore
this->semaphore->post();
}
void startThread()
{
// Start the thread (Pseudo code)
CreateThread(threadHelper, this, ...);
}
private:
static void threadHelper(void* param)
{
((MyWorkerThread*)param)->thread();
}
/// The thread method
void thread()
{
// Wait for semaphore to be invoked
semaphore->wait();
cout << blah << endl;
}
string blah;
boost::interprocess::interprocess_semaphore* semaphore;
};
そして、これが私の「素朴な」ポーリングコードです。
class MyWorkerThread_NaivePolling
{
public:
MyWorkerThread_NaivePolling()
{
workReady = false;
}
/// Do work asynchronously
void injectWork(string blah)
{
section.lock();
this->blah = blah;
this->workReady = true;
section.unlock();
}
void startThread()
{
// Start the thread (Pseudo code)
CreateThread(threadHelper, this, ...);
}
private:
/// Uses Win32 CriticalSection
class MyCriticalSection
{
MyCriticalSection();
void lock();
void unlock();
};
MyCriticalSection section;
static void threadHelper(void* param)
{
((MyWorkerThread*)param)->thread();
}
/// The thread method
void thread()
{
while (true)
{
bool myWorkReady = false;
string myBlah;
// See if work set
section.lock();
if (this->workReady)
{
myWorkReady = true;
myBlah = this->blah;
}
section.unlock();
if (myWorkReady)
{
cout << blah << endl;
return;
}
else
{
// No work so sleep for a while
Sleep(50);
}
}
}
string blah;
bool workReady;
};
乾杯、
ジョン