ネタ元 → 並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」
いいかインドリ、まぢもんの「生産者/消費者のイディオム」っちゅーのはこぉやるんだよ!
/*
cl -EHsc -openmp -MD -I<TBB_INC_DIR> prodcons.cpp -link -libpath:<TBB_LIB_DIR>
*/
#include <iostream> // std::cout,endl
#include <cstdlib> // std::rand
#include <tbb/tbb.h> // tbb::*
/*
* 生産者
*/
class Producer : public tbb::task {
tbb::concurrent_bounded_queue<int>& stock;
tbb::mutex& mutex;
public:
Producer(tbb::concurrent_bounded_queue<int>& s, tbb::mutex& m) : stock(s), mutex(m) {}
tbb::task* execute() {
int remains = 1000; // 残り生産量
while ( remains > 0 ) {
int produced = rand()%100; // 生産量
if ( remains < produced ) produced = remains; // 作りすぎないように
remains -= produced;
{
tbb::mutex::scoped_lock lock(mutex); // 出力中、mutexでロック
std::cout << "produce " << produced << ", "
<< remains << " remains." << std::endl;
}
stock.push(produced);
}
stock.push(-1); // terminator
std::cout << "end of produce.\n";
return 0;
}
};
class Consumer : public tbb::task {
tbb::concurrent_bounded_queue<int>& stock;
tbb::mutex& mutex;
public:
Consumer(tbb::concurrent_bounded_queue<int>& s, tbb::mutex& m) : stock(s), mutex(m) {}
tbb::task* execute() {
int consumed = 0; // 消費総量
int onstore = 0; // 店頭在庫
int n = 0;
while ( n >= 0 ) {
int tobeconsume = rand()%100; // 消費量
while ( onstore < tobeconsume ) { // 店頭に十分な在庫が確保できるまで
stock.pop(n); // 在庫から取り出す
if ( n < 0 ) { // 生産終了したならおしまい
tobeconsume = onstore;
break;
}
onstore += n; // 店頭在庫を増やす
}
onstore -= tobeconsume; // 販売
consumed += tobeconsume;
{
tbb::mutex::scoped_lock lock(mutex); // 出力中、mutexでロック
std::cout << "consume " << tobeconsume << ", "
<< consumed << " consumed so far." << std::endl;
}
}
std::cout << "end of consume.\n";
return 0;
}
};
class Market : public tbb::task {
tbb::concurrent_bounded_queue<int> stock;
tbb::mutex mutex;
public:
Market(int stock_capacity) {
stock.set_capacity(stock_capacity);
}
tbb::task* execute() {
// 生産者と消費者を生成し、並列実行して双方の終了を待つ
Producer& p = *new( allocate_child() ) Producer(stock,mutex);
Consumer& c = *new( allocate_child() ) Consumer(stock,mutex);
set_ref_count(3);
spawn(c);
spawn_and_wait_for_all(p);
std::cout << "market closed." << std::endl;
return 0;
}
};
int main() {
Market& market = *new(tbb::task::allocate_root()) Market(16);
tbb::task::spawn_root_and_wait(market);
std::cout << "demonstration over." << std::endl;
}
うわー、TBBスゲー!
ロクにマニュアル読まんでもexamplesの真似っこしてたらできちゃったー♪