SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

C++11 : スレッド・ライブラリひとめぐり

Visual Studio 2012 RC であそんでみたよ

  • X ポスト
  • このエントリーをはてなブックマークに追加

1:thread

 それでは、C++11のスレッド・ライブラリを使った版をご覧ください。

リスト6
void multi(int M, int nthr) {
  vector<thread> thr(nthr);
  vector<int> count(nthr);
  div_range<> rng(2,M,nthr);

  chrono::system_clock::time_point start = chrono::system_clock::now();
  for ( int i = 0; i < nthr; ++i ) {
    thr[i] = thread([&,i](int lo, int hi) { count[i] = count_prime(lo,hi); }, 
                    rng.lo(i), rng.hi(i));
  }
  int result = 0;
  for ( int i = 0; i < nthr; ++i ) {
    thr[i].join();
    result += count[i];
  }
  chrono::duration<double> sec = chrono::system_clock::now() - start;

  cout << result << ' ' << sec.count() << "[sec] : " << nthr << endl;
}

int main() {
  const int M = 100000;
  for ( int i = 1; i < 10; ++i ) multi(M, i);
}

 いかがです? Windows APIによる実装と比べるとあっけないほどに簡単、std::threadのコンストラクタにスレッドのエントリとそれに与える引数とを食わせるだけでスレッドが生成されて動き出します。あとは join() で完了を待つだけ。

 コンストラクタに引き渡すスレッド・エントリは()できるもの、つまりファンクタならなんでもOKです。

リスト7
 void count_prime_function(int lo, int hi, int& result) {
   result = count_prime(lo, hi);
 }

class count_prime_class {
   int& result_;
public:
  count_prime_class(int& result) : result_(result) {}
  void operator()(int lo, int hi) { result_ = count_prime(lo, hi); }
};

void multi(int M) {
  thread thr[3];
  int    count[3];
  div_range<> rng(2,M,3);

  auto count_prime_lambda = [&](int lo, int hi) { count[2] = count_prime(lo,hi); };

  chrono::system_clock::time_point start = chrono::system_clock::now();
  // 関数ポインタ, クラスインスタンス, lambda式からスレッドを作る
  thr[0] = thread(count_prime_function,        rng.lo(0), rng.hi(0), ref(count[0]));
  thr[1] = thread(count_prime_class(count[1]), rng.lo(1), rng.hi(1));
  thr[2] = thread(count_prime_lambda,          rng.lo(2), rng.hi(2));
  for ( thread& t : thr ) t.join();
  chrono::duration<double> sec = chrono::system_clock::now() - start;

  cout << count[0] + count[1] + count[2] << ' '
       << sec.count() << "[sec]" << endl;
}

2:async/future

 threadを使った場合、join()による完了待ちの後、結果の参照(読み取り)を行うのですが、async/futureを使えば完了待ちと結果の参照が簡略化されます。戻り値(結果)を返すファンクタと引数をasyncに与えるとfutureが返ってきます。そのfutureに対するget()ひとつで、完了待ちと結果の参照が行えます。

リスト8
class count_prime_class {
public:
  int operator()(int lo, int hi) { return count_prime(lo, hi); }
};

void multi(int M) {
  future<int> fut[3];
  div_range<> rng(2,M,3);

  auto count_prime_lambda = [&](int lo, int hi) { return count_prime(lo,hi); };

  chrono::system_clock::time_point start = chrono::system_clock::now();
  // 関数ポインタ, クラスインスタンス, lambda式からfutureを作る
  fut[0] = async(count_prime,         rng.lo(0), rng.hi(0));
  fut[1] = async(count_prime_class(), rng.lo(1), rng.hi(1));
  fut[2] = async(count_prime_lambda,  rng.lo(2), rng.hi(2));
  int result = fut[0].get() + fut[1].get() + fut[2].get();
  chrono::duration<double> sec = chrono::system_clock::now() - start;

  cout << result << sec.count() << "[sec]" << endl;
}

次のページ
3:mutex/atomic

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6639 2012/06/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング