SHOEISHA iD

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

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

特集記事

インテルTBBによる選択ソートの高速化

スレッドを意識しないマルチスレッドアプリケーション


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

 この記事では、選択ソートアルゴリズムを「STL」で実装し、インテルが公開しているマルチコアCPU向けのC++テンプレートライブラリ「インテル スレッディング・ビルディング・ブロック」を使ってマルチスレッドによる高速化を試みます。

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

はじめに

 ソートアルゴリズムの実装は代入/比較/繰り返しなど、プログラミングを学ぶ上での基本がきっちり詰まっていて、ビギナーのトレーニングには格好の題材です。簡単なソートアルゴリズムの代表格といえばバブルソート選択ソートでしょうか。

 この記事では、選択ソートアルゴリズムを「STL」(C++の標準テンプレートライブラリ;Standard Template Library)で実装し、インテルが公開しているマルチコアCPU向けのC++テンプレートライブラリ「インテル スレッディング・ビルディング・ブロック」(インテルTBB)を使ってマルチスレッドによる高速化を試みます。

選択ソートのSTLによる実装

 選択ソート(selection sort)のアルゴリズムはバブルソート以上に単純です。配列 data[N] を昇順にソートするには

data[i]~data[N-1]の中から最も小さい要素を探し、
それとdata[i]とを交換する

を i = 0~N-1 に対してくり返すだけ。data[0]~data[N-1]中の最小要素とdata[0]とを交換すれば、当然data[0]が最小となります。次に(data[0]を除いた)data[1]~data[N-1]中の最小要素をdata[1]と交換するのでdata[1]は2番目に小さい要素となります。以下この操作を繰り返せばソート完了という次第。

 STLの<algorithm>には最も小さい要素(を指すイテレータ)を返すmin_element、および2つの要素をイテレータを介して交換するiter_swapがありますから、選択ソートの実装はきわめて簡単です。

// 選択ソート
template<typename Iterator>
void selection_sort(Iterator first, Iterator last) {
  while ( first != last ) {
    // [first,last)中の最小要素をfirstと交換
    std::iter_swap(first, std::min_element(first,last));
    ++first;
  }
}

 10行足らずで書けてしまう選択ソート、性能はいかがなものでしょう。お試しに文字列の並び、vector<string> をソートしましょうか。前準備としてソートアルゴリズムを関数オブジェクトに仕立てておきます。

class sort_base {
public:
    typedef std::vector<std::string>::iterator iterator;
protected:
  iterator first_;
  iterator last_;
  virtual void do_sort() const =0; // ←導出クラスではコレを再定義して処理を書く
public:
  sort_base(iterator first, iterator last) : first_(first), last_(last) {}
  void operator()() const { 
    do_sort(); // ソートして...
    // 昇順に並んでいることを確認
    assert( std::adjacent_find(first_, last_, std::greater<std::string>()) == last_ );
  }
};

/*
 * 至極真っ当な選択ソート
 */
class normal_sort : public sort_base {
public:
  normal_sort(iterator first, iterator last) : sort_base(first,last) {}
protected:
  virtual void do_sort() const {
    selection_sort(first_, last_);
  }
};

// 関数オブジェクトを評価(実行)し、処理時間を測定する
void execute(const sort_base& sort_fn) {
  tbb::tick_count start = tbb::tick_count::now();
  sort_fn();
  std::cout << (tbb::tick_count::now() - start).seconds() << " [sec]\n";
}

int main() {

  std::vector<std::string> source;
  std::vector<std::string> input;

  { // ソート対象を生成。
    // A..Hの順列(8!個)を用意し、
    std::string value = "ABCDEFGH";
    do { source.push_back(value);
    } while ( std::next_permutation(value.begin(), value.end()) );
    // その順序をかき混ぜる。
    std::random_shuffle(source.begin(),source.end());
  }

  { // フツーに選択ソート
    input = source;
    std::cout << "normal_sort ....... " << std::flush;
    execute(normal_sort(input.begin(), input.end()));
  }
}

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

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

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

メールバックナンバー

次のページ
データの分割による高速化

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

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

もっと読む

この記事の著者

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

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

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

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

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/5039 2012/07/09 15:32

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング