SHOEISHA iD

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

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

特集記事

並列処理のためのC++ライブラリ拡張
~C++17: 並列STLの概要

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

 STLを多用したアプリケーションを可能な限り速く動作させる必要に迫られました。実験実装ではまずまずのスピードを叩き出してくれてたのですが、本番の稼働では思いのほか多量のデータを扱うことになりそうで、当初の想定より数割増し速くないとマズいことが判明しちゃいました。今以上に速くできるかコードを眺めてみたけれど、データ構造とアルゴリズムにはこれ以上の改善の余地がなさそうなんです。幸いなことに4coreのCPUを積んだマシンを使うとのことで、マルチスレッドによる高速化に望みを託すことになりました。

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

C++11の標準ライブラリ<thread>を使った並列化

 大量のデータを分割し、複数のスレッドに分担させて処理時間を稼ぐことを考えます。スレッドに関わるAPIは、WindowsならCreateThreadやWaitForNltipleObjectなど、Linuxならpthread_xxxxと、OSによって異なるのですが、C++11では標準ライブラリ<thread>がOSごとの差異を吸収してくれているのが嬉しいところ。大量のデータを詰め込んだvectorを2つのスレッドでソートしてみます。

list01 sort_thread.cpp
#include <iostream>  // cout, endl
#include <thread>    // thread
#include <algorithm> // inplace_merge, etc.
#include <chrono>    // clock, time_point, duration
#include <iterator>  // advecnce, distance
#include <vector>    // vector
#include <numeric>   // iota
#include <cassert>   // assert

using namespace std;

template<typename Iterator>
void faster_sort(Iterator first, Iterator last) {
  // mid : first と last の中間地点
  Iterator mid = first;
  advance(mid, distance(first, last)/2);
  // シーケンスの前半(first~mid)を子スレッドでsort
  thread thr(&sort<Iterator>, first, mid);
  // 後半(mid~last)は自スレッドでsort
  sort(mid, last);
  // 子スレッドの完了を待って
  thr.join();
  // 前半と後半をマージする
  inplace_merge(first, mid, last);
}

// 関数fの実行時間を計測する
template<typename Function>
void measure(Function f) {
  using namespace std::chrono;
  auto start = high_resolution_clock::now();
  f();
  auto stop = high_resolution_clock::now();
  std::cout << duration_cast<microseconds>(stop - start).count() << std::endl;
}

int main() {
  const int N = 4000000;
  vector<int> data(N);
  iota(begin(data), end(data), 0);

  reverse(begin(data), end(data));
  cout << "std::sort    ";
  measure([&]() { sort(begin(data), end(data)); });
  assert( is_sorted(begin(data), end(data)) );

  reverse(begin(data), end(data));
  cout << "faster_sort ";
  measure([&]() { faster_sort(begin(data), end(data)); });
  assert( is_sorted(begin(data), end(data)) );

}

 データの半分を子スレッドに任せたところ処理スピードは数割増し、まずまずの結果です。しかしながら、このやり方には少々不満が残ります。

 第一にはスケーラビリティに欠けること。データを親子2つのスレッドに分担させていて、同時に処理しているスレッド数は2に固定されていますから、リッチなマシンに乗せ換えてもCPUのコア数に応じて速くなってはくれんのです。

スケーラブルなマルチスレッド・ライブラリの利用

 スケーラブルなマルチスレッド・ライブラリには、例えばIntel TBB(Treading Building Blocks)、あるいはVisual C++に付属するPPL(Parallel Pattern Library)などがあります。PPLのソート関数:parallel_sortを使ってみると:

list02 sort_PPL.cpp
#include <ppl.h>     // parallel_sort

#include <iostream>  // cout, endl
#include <chrono>    // clock, time_point, duration
#include <vector>    // vector
#include <array>     // array;
#include <numeric>   // iota

using namespace std;

// 関数fの実行時間を計測する
template<typename Function>
void measure(Function f) { /* 省略 */ }

int main() {
  const int N = 4000000;
  vector<int> data(N);
  iota(begin(data), end(data), 0);

  reverse(begin(data), end(data));
  cout << "std::sort:     ";
  measure([&]() { sort(begin(data), end(data)); });

  reverse(begin(data), end(data));
  cout << "parallel_sort: ";
  measure([&]() { concurrency::parallel_sort(begin(data), end(data)); });

}

 論理コア8つとなると流石に速いですね。

 それじゃ現コードをPPLで再実装して、めでたしめでたしかというとさにあらず、PPLが用意してくれている並列アルゴリズムは:

  • parallel_for
  • parallel_for_each
  • parallel_invoke
  • parallel_transform
  • parallel_reduce
  • parallel_sort
  • parallel_buffered_sort
  • parallel_radixsort

 ……10個にも満たない。STL <algorithm>のアルゴリズム群に比べれるとおハナシにならんくらいに少ないので、PPLは再実装の手間がバカにならんのです。

会員登録無料すると、続きをお読みいただけます

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

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

メールバックナンバー

次のページ
「ParallelSTL」 ── 近未来の並列STL

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

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

もっと読む

この記事の著者

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

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

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

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

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8058 2014/09/26 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング