フューチャを使用してこれを実現する方法については、Boost.Thread フューチャのドキュメントを参照してください。async
また、オブジェクトを使用して手動で (難しい方法で) 行う方法も示しthread
ます。
このシリアルコードを考えると:
double run_sim(Data*);
int main()
{
const unsigned ntasks = 50;
double results[ntasks];
Data data[ntasks];
for (unsigned i=0; i<ntasks; ++i)
results[i] = run_sim(data[i]);
}
単純な並列バージョンは次のようになります。
#define BOOST_THREAD_PROVIDES_FUTURE
#include <boost/thread/future.hpp>
#include <boost/bind.hpp>
double run_task(Data*);
int main()
{
const unsigned nsim = 50;
Data data[nsim];
boost::future<int> futures[nsim];
for (unsigned i=0; i<nsim; ++i)
futures[i] = boost::async(boost::bind(&run_sim, &data[i]));
double results[nsim];
for (unsigned i=0; i<nsim; ++i)
results[i] = futures[i].get();
}
boost::async
は遅延関数をまだサポートしていないため、非同期呼び出しごとに新しいスレッドが作成されるため、一度に 50 のスレッドが生成されます。これはパフォーマンスが非常に悪い可能性があるため、小さなブロックに分割できます。
#define BOOST_THREAD_PROVIDES_FUTURE
#include <boost/thread/future.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
double run_sim(Data*);
int main()
{
const unsigned nsim = 50;
unsigned nprocs = boost::thread::hardware_concurrency();
if (nprocs == 0)
nprocs = 2; // cannot determine number of cores, let's say 2
Data data[nsim];
boost::future<int> futures[nsim];
double results[nsim];
for (unsigned i=0; i<nsim; ++i)
{
if ( ((i+1) % nprocs) != 0 )
futures[i] = boost::async(boost::bind(&run_sim, &data[i]));
else
results[i] = run_sim(&data[i]);
}
for (unsigned i=0; i<nsim; ++i)
if ( ((i+1) % nprocs) != 0 )
results[i] = futures[i].get();
}
hardware_concurrency()
4 が返された場合、これにより 3 つの新しいスレッドが作成され、スレッドrun_sim
内で同期的に呼び出され、さらに 3 つの新しいスレッドが作成されてから同期的に呼び出されます。これにより、メイン スレッドが作業の一部を停止するため、一度に 50 個のスレッドがすべて作成されるのを防ぎ、他のスレッドの一部を完了することができます。main()
run_sim
上記のコードには最新バージョンの Boost が必要です。C++11 を使用できる場合は、標準 C++ を使用する方が少し簡単です。
#include <future>
double run_sim(Data*);
int main()
{
const unsigned nsim = 50;
Data data[nsim];
std::future<int> futures[nsim];
double results[nsim];
unsigned nprocs = std::thread::hardware_concurrency();
if (nprocs == 0)
nprocs = 2;
for (unsigned i=0; i<nsim; ++i)
{
if ( ((i+1) % nprocs) != 0 )
futures[i] = std::async(boost::launch::async, &run_sim, &data[i]);
else
results[i] = run_sim(&data[i]);
}
for (unsigned i=0; i<nsim; ++i)
if ( ((i+1) % nprocs) != 0 )
results[i] = futures[i].get();
}