web-dev-qa-db-ja.com

C ++ 11:std :: thread pooled?

C++ 03では、常にいくつかのスレッドを実行し続ける自己構築のスレッドプールでpthreadを使用しました(pthread_createが遅いため)。このようにして、パフォーマンスの問題を考えずに小さなタスクのスレッドを起動できました。 。

現在、C++ 11にはstd::threadがあります。標準では特定の実装について何も言われていないので、私の質問は標準ライブラリの実装に関するものです。彼らは一般に、std::threadsの構築が安価な(そして、たとえばposixでpthread_createを呼び出さない)プールされたアプローチを選択していますか、それともstd::threadは単なるラッパーですか?

つまり、スレッドプールはC++ 11でも引き続き推奨されますか、それとも必要に応じてstd::threadを作成し、パフォーマンスを標準ライブラリに任せる必要がありますか?

38
lucas clemente

一般的に、std::threadは、基礎となるシステムプリミティブの最小限のラッパーである必要があります。たとえば、pthreadプラットフォームを使用している場合、作成するスレッドの数に関係なく、すべて一意のpthread_t idで作成されることを次のプログラムでテストできます(つまり、オンザフライで作成され、スレッドプールから借用されていません):

#include <assert.h>
#include <mutex>
#include <set>
#include <thread>
#include <vector>

#include <pthread.h>

int main() {
  std::vector<std::thread> workers;
  std::set<long long> thread_ids;
  std::mutex m;
  const int n = 1024;

  for (int i = 0; i < n; ++i) {
    workers.Push_back(std::thread([&] {
      std::lock_guard<std::mutex> lock(m);
      thread_ids.insert(pthread_self());
    }));
  }
  for (auto& worker : workers) {
    worker.join();
  }
  assert(thread_ids.size() == n);

  return 0;
}

したがって、スレッドプールは依然として完全に意味をなします。そうは言っても、C++委員会のメンバーがstd::async(IIRC)に関してスレッドプールについて議論したビデオを見たことがありますが、今のところ見つけることができません。

24
dorserg

std::threadは実行のスレッドです。限目。それがどこから来て、どのようにそこに到達するか、「実際の」スレッドのプールがあるかどうかなどは、すべて標準とは無関係です。スレッドのように動作する限り、std::thread

今、std::threadは、実際のOSスレッドであり、スレッドプールなどから引き出されたものではありません。ただし、C++ 11では理論的にstd::threadプールから引き出されたものとして実装されます。

11
Nicol Bolas

std::threadは、抽象化コストの点で非常に安価であると考えられています。低レベルのものです。私が理解しているように、標準ライブラリの実装はおそらく、基礎となるOSメカニズムをできるだけ密接にラップするため、スレッド作成のオーバーヘッドが類似または同等であると想定できます。

私は特定の実装については知りませんが、C++ Concurrency In Actionを読むことからの私の間接的な理解は、標準がそれらが最も効率的な方法を実用的に使用することを示唆していることです。著者は確かに、DIYに比べてコストは多かれ少なかれ無視できると考えているように見えました。

ライブラリは概念的にBoostに似ているので、Boost実装を使用して結論を​​出すことは、それほど大げさなことではないと思います。

基本的に、指定されていないため、質問に対する直接的な回答はないと思います。非常に薄いラッパーの実装を目にする可能性が高くなるように思えますが、ライブラリライターが効率の向上を提供する場合、スレッドプールの使用は制限されないと思います。

5
Elliott

最初に、あなたが述べたように、C++標準は基本的にライブラリの実装を指定していません。しかし、C++標準ライブラリshallの実装者は、「as-if」ルールに従います。

たとえば、std::thread振る舞うif基になるAPIのシンラッパーまたはthread-poolなどの効率的な実装の場合、新しいスレッドが作成されます。 (ここで、「スレッド」は、具体的なOSネイティブスレッドではなく、C++ 11仕様の抽象実行スレッドを意味します)

スレッドプールの実装。

  • C++コンパイラおよびライブラリは、C++スレッド固有のリソース(つまり、thread_local変数)、および実行時に連携して連携する必要があります。
  • 上記の条件が満たされていても、OS固有のスレッドリソース(WindowsのTLS、pthreadのTSSなど)と連携することは不可能のようです。

したがって、ほとんどのstd::thread実装は、基礎となるスレッドAPIの単なるラッパーです。

2
yohjp