要件定義の不安をなくす。要件定義の不安をなくす。ユニファのバックエンド分割に学ぶイノベーションメタバース開発に必要な技術の基本知識をおさらい。Boost」など、さまざまなカンファレンスを企画・運営しています。BOOKS(コードジン・ブックス)は、CodeZineの連載からカットアップした、開発現場の課題解決に役立つ書籍シリーズです。書籍WebサイトParallelReduceSampleの並列処理についてParallelReduceSampleはparallel_reduceテンプレートを使用しています。parallel_reduceテンプレートを使用するために、並列処理を行うオブジェクトは4つの条件を満たさねばなりません。1つ目は、専用のコピー・コンストラクター(インテルTBBでは「分割コンストラクター」と呼びます)を実装することです。普通のコピー・コンストラクタと区別するためにtbb::splitクラスを指定しなくてはなりません。2つ目は、デストラクターを用意することです。3つ目は、operator()を多重定義することです。4つ目は、joinというメソッドを定義しなくてはなりません。詳細は後でサンプルの解説と共に行います。ParallelReduceSampleの並列処理部分は下記の通りです。}};分割コンストラクターでは、初期化リスト内で渡されたオブジェクトの任意の値をコピーし、分析によって導出する値(最大値など)については初期化しています。このコンストラクターは、parallel_reduceテンプレートがオブジェクトを分割する時に呼び出します。この時点ではまだ分析値(総売上、最大金額など)は導出されていませんので初期値に設定しています。各項目を加算し、それと同時に最小値と最大値を割り出しています。この時点では、分割されたオブジェクト内での計算課程ですので、全体としての合計値や最大/最小値が割り出されているわけではないことと、今回はconstが指定されていないことに注意して下さい。このテンプレートでは変更が予想されますのでconstを定義してはなりません。ここは間違えやすい点ですので注意して下さい。全体としての各種値を出すのは、joinメソッドの仕事です。parallel_reduceテンプレートは最初に、対象となるオブジェクト(このサンプルではSales)を分割していきオブジェクトのコピーを作ります。分割が終わったらその範囲内で処理を行います。最後に、各コピーしたオブジェクトのjoinメソッドを呼び出して、2つのオブジェクトを結合していき、最終的に1つのオブジェクトになるまでそれを繰り返します。joinメソッドの引数が自分と同じオブジェクト(このサンプルではSales)なのはこれが理由です。ParallelReduceSampleを実行して下さい。並列処理の処理効率が良いことが確認できます。parallel_reduceテンプレートを使う上で注意するべき点があります。それは、演算の丸め誤差です。並列処理では処理の実行順序がバラバラで、割り算の計算結果が毎回違います。100/4/3/2を計算するとします。直列では毎回(((100/4)/3)/2)の順序で計算されます。並列では((100/4)/(3/2))の様に計算されます。従って、丸め誤差により計算結果が同じではなくなります。並列プログラミングを初めて行った際によく起こる過ちですので十分に注意して下さい。parallel_reduceテンプレートは結果を結合する処理がありますので、どうしてもparallel_forテンプレートよりも低くなります。parallel_forテンプレートを利用するとよいでしょう。今回2つのテンプレートを通じて、ループ処理を並列化する方法について解説しました。並列化に慣れていない人はあまりピンと来ないと思いますが、考え方そのものは非常に単純です。ループの処理は分解して考えると、次のように処理をしていることになります。);//以下省略この処理をよく見ると、各々の処理が他の処理に依存せずに、限られた範囲内で処理をしています。いうことは、マルチコアプロセッサならば、処理1と処理2が同時に行えると考えるのは自然です。これがparallel_forテンプレートの考え方です。次に、ParallelReduceSampleの様に要素全体で処理をする場合、タスクを分割してその範囲内で最大値などを求め、後でその結果を突き合わせて判断をするようにすれば、マルチコアプロセッサで同時に複数のタスクが処理できることになります。これが、parallel_reduceテンプレートの考え方です。この2つの考え方を改めて考えると、普段我々人間がしている仕事と同じです。私たちは多くの場合、1つのプロジェクトの作業を分割して複数の人間で作業しますし(parallel_forテンプレートと同じ)、各プログラマーが複数のオブジェクトをプログラミングしてからそれを統合して1つのシステムを実装します(parallel_reduceテンプレートと同じ)こうしてよく考えてみれば、並列プログラミングもそれ程特殊な考え方でないことが分かって頂けると思います。まとめ今回は、インテルTBBのparallel_forテンプレートとparallel_reduceテンプレートの使い方を解説しました。その根底に流れる「ループ処理を並列化する」という考え方も解説しました。今まで並列プログラミングに対して苦手意識をもっている方は多いと思います。今回の記事を読めば、並列プログラミングの考え方がそれ程特殊なものではなく、普段我々人間がしていることと大差がないことが分かって頂けると思います。並列プログラミングは今後当たり前のものとなります。その準備のお手伝いができれば幸いです。次回は、より高度な並列プログラミングの概念を噛み砕いて解説します。インテルTBBのスレッドクラスマルチスレッドを安全に実行するスレッドセーフとインテルTBBのコンテナもっと読むこの記事の著者インドリ(インドリ)分析・設計・実装なんでもありのフリーエンジニア。ブログ「無差別に技術をついばむ鳥(http://indori.blog32.fc2.com/)」の作者です。アドバイザーをしたり、システム開発したり、情報処理技術を研究したりと色々しています。3.12」の最初のベータ版がリリース新着記事一覧を見るイベント今後の予定を見るCodeZineは、株式会社翔泳社が運営するソフトウェア開発者向けのWebメディアです。「デベロッパーの成長と課題解決に貢献するメディア」をコンセプトに、現場で役立つ最新情報を日々お届けします。イラストの無断転載を禁じます。記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。