160 の並列スレッド (8 Intel E7-8870) と 0.5 TBytes のメモリを備えたマシンで tbb::parallel_for を使用しようとしています。これは、カーネル 3.2.0-35-generic #55-Ubuntu SMP を使用する現在の Ubuntu システムです。TBB はパッケージ libtbb2 バージョン 4.0+r233-1 からのものです
非常に単純なタスクでも、「bad_alloc」または「thread_monitor リソースが一時的に使用不可」のいずれかで、リソースが不足する傾向があります。私はそれをこの非常に単純なテストに煮詰めました:
#include <vector>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include "tbb/tbb.h"
#include "tbb/task_scheduler_init.h"
using namespace tbb;
class Worker
{
std::vector<double>& dst;
public:
Worker(std::vector<double>& dst)
: dst(dst)
{}
void operator()(const blocked_range<size_t>& r ) const
{
for (size_t i=r.begin(); i!=r.end(); ++i)
dst[i] = std::sin(i);
}
};
int main(int argc, char** argv)
{
unsigned int n = 10000000;
unsigned int p = task_scheduler_init::default_num_threads();
std::cout << "Vector length: " << n << std::endl
<< "Processes : " << p << std::endl;
const size_t grain_size = n/p;
std::vector<double> src(n);
std::cerr << "Starting loop" << std::endl;
parallel_for(blocked_range<size_t>(0, n, grain_size), RandWorker(src));
std::cerr << "Loop finished" << std::endl;
}
典型的な出力は
Vector length: 10000000
Processes : 160
Starting loop
thread_monitor Resource temporarily unavailable
thread_monitor Resource temporarily unavailable
thread_monitor Resource temporarily unavailable
エラーはランダムに発生し、n が大きいほど頻繁に発生します。ここでの 1,000 万という値は、それらがかなり定期的に発生するポイントです。それにもかかわらず、マシンの特性を考えると、これはメモリを使い果たすことはありません (私はこれらのテストに単独で使用しています)。
粒度が導入されたのは、tbb がワーカーのインスタンスを作成しすぎたため、n がさらに小さい場合に失敗しました。
多数のスレッドを処理するように tbb を設定する方法についてアドバイスをくれる人はいますか?