Archive for the ‘本’ category

並行コンピューティング 第10章 & 第11章

8月 1st, 2010

今回でラスト。

◯第10章 グラフアルゴリズム
深さ優先探索と幅優先探索の並行実装例を紹介している。どちらも逐次処理だと再帰実装がよく用いられるが、再帰と並行処理の相性が悪いためキュー・スタックをつかって探索位置を管理する必要がある。スタックを使えば深さ優先探索に、キューを使えば幅優先探索になる。

次が最短経路探索問題のアルゴリズム。Floyd-Warshall法やDijkstra法があるけど、本ではFloyd-Warshall法だけTBBを使って紹介。特筆事項は無し。

最後が最小スパニングツリーを見つけるアルゴリズム。KruskalとPrimがあるけど、本ではPrimをTBBとOpenMPを組み合わせて並列化する手法を紹介。これまでの総集編といった趣。

◯第11章 スレッド対応ツール
宣伝じゃないと言いながらもIntelの製品をパワープッシュ。
著者はIntelの社員さんなのは割り引いて聞く必要があるかも。

◯全部読んでの感想
会社のメンバで輪講したのですが、後半はアルゴリズムの解説が多く、ソースの実装もいまいちだったように感じました。さらに後半は元の文が悪いのか、訳が悪いのか読んでいてわからないところが頻出しました。並行処理の基礎知識を習得するのに5章までを読むのにはいいかもしれません。後半は並行処理実装のアイデアを色々もらえるけど、いくらか疑ってかかったほうがいいと思います。

並行コンピューティング技法 第8章&第9章

7月 3rd, 2010

間が開いたので2回分まとめて。

◯第8章 ソート
プロセッサ時間の80%以上はソートに費やされるとも言われる。ソートを高速化すれば処理全体の高速化につながりやすい。
この章では5つのアルゴリズムについて並行化を検討している。

バブルソートは左右で要素を比較して、小さい値(または大きい値)が泡のように上がっていくことからそう呼ばれる。スレッドの順番が入れ替わらない限り、頭から複数スレッドで配列を走査してもソートは保証される。このアルゴリズムは波の動きに似ているためwavefront法とも呼ばれる。単に前のスレッドを抜かさないようにするとオーバーヘッドが大きくなるため、配列をいくつかのゾーンに区切って制御すると良い。

奇偶転置ソートは「奇数インデックスの比較→偶数インデックスの比較→奇数インデックスの比較」を繰り返してソートを行う。隣接同士の比較・変更しか起こりえないので、データ分解による並列化が容易。

シェルソートは配列全体を適当なサイズで分割し、分割された範囲内でソートを行う。徐々に分割サイズを小さくすることでソートを行ない、要素が大きく動かせることからソートが早く行える特徴がある。逐次処理では有効だが、並行処理ではキャッシュが効きにくくなり並行処理では短所にもなりうる。

クイックソートは逐次処理では最も一般的なソートである。再帰を使って実装することもあるが、並行処理には不向きなのでキューを使うなりして再帰は避ける必要がある。スレッドをプールし、ソート対象のインデックス範囲をキュー/スタックに入れておくことでスレッド間の競合を抑え、処理を並行化することができる。処理が終わったかどうかを判断し、スレッドに処理を辞めるよう促す実装が若干面倒。

奇数ソートはソート対象を二進数と考え、上位ビット/下位ビットを使ってソートしていく。同じ値の順序が保たれる安定ソートであることが特徴。実装では複数ビットをまとめてソートすることになるが、ソート後の移動先の計算がかなり面倒。本でもトリッキーに思える例が紹介されていた。

◯第9章 サーチ
未ソートデータに対するサーチと、ソート済みデータに対するサーチの例を紹介。

未ソートデータの場合、全要素を見ないといけないので、配列をデータ分解してスレッドに処理させる。探索対象のデータが見つかったときに処理を打ち切る工夫を入れるぐらいでOK。素直な実装になる。

ソート済みデータの場合、逐次処理では2分探索が一般的。並行処理ではこの考え方を発展させてN分探索すると良い。配列をNつに分解し、探索対象がどちら側にあるか(右側、左側、見つかった)を調べる。探索対象のデータは向きが異なるブロックに含まれるため、このブロックを探し出し、内部をさらにNつに分解して再帰的に探索を続ける。

posted with amazlet at 10.07.03
Clay Breshears
オライリージャパン
売り上げランキング: 6200

並行コンピューティング技法 第7章

5月 9th, 2010

この章は内容がイマイチだったので手短に。内容はMapReduceについて。

最初にMapReduceの説明があり、直後にリダクション処理(配列の和を求める処理)のMapReduce実装例が載ってるんだけど、前章までに扱ってた処理と何が違うのかこれだけではさっぱりわからない。Map処理とReduce処理をきちんと分けた処理にする必要はわかるんだけど、1つのCPU上で動くようにコードを書いても読者にメリットは伝わらないと思う。MapReduce自体の説明は2006年8月31日のRadium Software Developmentがおすすめ。

7章の残りはスレッドのバリア同期の実装について。並行コンピューティングの理解を深めるために必要となってるけど、Pthreadでも提供されている機能だし、自前実装するよりも用意されているものを使った方がいいんじゃないかな、多くの場合では。

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング
Clay Breshears
オライリージャパン
売り上げランキング: 11404

企業の研究者をめざす皆さんへ

5月 4th, 2010
企業の研究者をめざす皆さんへ―Research That Matters
丸山 宏
近代科学社
売り上げランキング: 131342
おすすめ度の平均: 4.5

4 IBM東京基礎研究所のようす
5 企業研究者を目指す学生は勿論のこと、企業研究者にも参考になる。

この本を読んでいてどこか既視感があったのですが、情熱プログラマー ソフトウェア開発者の幸せな生き方
に通じるところが非常に多い本です。情熱プログラマがソフトウェアエンジニアのキャリア構築について述べた本なら、こちらはリサーチエンジニアのキャリア構築について書かれた本です。必要とされる技術やバックグラウンドが多少異なるのかもしれませんが、世界基準で力を蓄え、世の中を大きく変える創造性を求められる点で抑えておくべき素養は似通ってくるのかもしれません。

本の冒頭部では研究者は「ものごとの原理に常に立ち返って真理を追求する姿勢を失ってはならず」かつ「お客様や社会の問題を常に意識して、それを解くための真理・原理・仕組みを考えていく」必要があると説いています。これから先自分の仕事が仕分けされないようにするには研究者としての本分を忘れず、世の中に貢献していく姿勢が求められます。研究者の貢献と言うと最近ではイノベーションという言葉で曖昧に表現されている感がありますが、この本では「どんな形であれ、インパクトの大きさで測られるべき」としています。Appleが出すようなセクシーな製品や、TEDで見れるような数年先の未来モデルだけではなく、Linuxのような世界中で使われるソフトウェアを開発することも立派なインパクトの一つとしています。この定義はこれまで「インパクトのある大きいことをやれ」とただ言われていただけに感じていた自分には
納得感が有るものでした。

その他、研究者として自らを伸ばしていくためにいくつものアドバイスがあります。

  • 目標となる人物・師を探すこと
  • 解くべき価値がある、いい問題を見つけること
  • 成果はすぐに使われない可能性があるので、きちんとした形(論理性のある文書、例えば論文)で残しておくこと。
  • コミュニケーションとは相手に”納得”してもらい、相手に次の行動を促すこと。
  • 見えないことはいないのと同じ。存在感を出すこと。
  • 外の世界を積極的に経験すること。

研究者としてのアドバイスの他に、IBM社内での取り組み事例が各所で紹介されていて、IBMという組織の巨大さ、底力を垣間見ることができます。自分が知っていたIBMとはずいぶん違う点もあり、ここも面白く読むことが出来ました。

大学で研究室に配属されたばかりの学生や、企業に就職して研究開発部門に配属された新人社員が読むと得られるものが多いと思います。この本はIBM東京基礎研究所内のイントラブログをつなぎ合わせる形で構成されていますが、複数の文書をつなぐために記述が冗長な所も見受けられます。もっと多くの人に読まれていい本だと思うので第2版が出るならこの点が改善されるといいなと感じました。

・・・

ちなみに自分の本は丸山さんからいただいたサイン付きです♪

並行コンピューティング技法 第6章

4月 23rd, 2010

いよいよアルゴリズムの並行化に着手する。今回は並列和、プリフィックススキャン、セレクションの3種類。

◯並列和
配列の和を全部求めるよくある処理。楽なのはOpenMPやTBBを使ってリダクション処理をそのまま利用すること。
自前で実装するなら配列をスレッド数で分割して個別に小計を計算。全スレッドが計算終わったら小計を全部足して合計をもとめるというやり方がおすすめ。

◯プリフィックススキャン
[3, 5, 2, 5, 7, 9, 4, 6]という配列を与えたときに[3, 8, 10 15, 22, 31, 35, 41]という配列を求める。配列のN番目に元の配列の0〜N番目までの和を入れておく処理に当たる。包含的プリフィックススキャンとも言うらしい。
先頭を覗いて[0, 3, 8, 10, 15, 22, 31, 35]の配列を求める排他的プリフィックススキャンの方法もある。

並列化の手法として、スレッド数で配列を分割し、個別にプリフィックススキャンを行う。次に末尾の要素を使って前後のチャンクに伝搬させる値を計算する。計算が終わったそれぞれのスレッドが担当するチャンクに値を加算してプリフィックススキャンを完了する。

さっきの例を3スレッドでやるとこんな感じになる。2と4のステップが並列化可能になる。
2から3、3から4に移るときに毎回スレッドを生成/破棄するとオーバーヘッドになるので、スレッドのイベント通知機能を上手く使って使いまわすのが吉。

1. 入力をスレッド数で分割
[3, 5, 2, 5, 7, 9, 4, 6] -> [3, 5, 2], [5, 7, 9], [4, 6]

2. 個別にプリフィックススキャン
[3, 5, 2], [5, 7, 9], [4, 6] -> [3, 8, 10], [5, 12, 21], [4, 10]

3. 配列の末尾の値で排他的プリフィックススキャンを行い、伝搬させる値を計算する
[3, 8, 10], [5, 12, 21], [4, 10] -> [10, 21, 10] -> [0, 10, 31]

4. 3で求めた値を2の処理結果にそれぞれ加算
[3, 8, 10]+0, [5, 12, 21]+10, [4, 10]+31 -> [3, 8, 10, 15, 22, 31, 35, 41]

◯セレクション
配列をソートしてN番目の値を取ってくるという処理。
ソートしてもいいけど、1回しか呼ばれないとか、適宜順番が変わるような配列だとセレクションがおすすめ。

公知のセレクションアルゴリズムがあって、その中でいくつかを並列化する。

1. 配列数がQ(本では5を勧めている)より小さければデータをソートして、k番目の要素を返す。Qより多ければ次のステップへ
2. チャンクから中央値を選ぶ(本では配列を分割して中央値を求め、その中からさらに中央値を求めるやり方をしているけど、配列の中身が適度にバラバラなら適当に選んでもいいかも)
3. データを A.中央値より小さい値を持つ B.中央値と同じ値である C.中央値より大きい値を持つ の3種類に分け、A,B,Cの数を数える。
4. 求めるk番目の要素がどこに入るかを調べる。Bに入るなら値を返して終了、AかCなら再帰的に1から処理を続ける。

本で高速化しているのはこのうちの2の処理、3の処理、4の処理の一部である。ポイントは4の処理で、再帰的に呼び出す際の配列の部分集合を使うのにプリフィックススキャンを使って詰め直し先のインデックス値を求めている。逐次処理に慣れきっていると重そうだけど、実際実行してみたら早いのかな? 要検証。

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング
Clay Breshears
オライリージャパン
売り上げランキング: 8422

情熱プログラマー ソフトウェア開発者の幸せな生き方

4月 15th, 2010
情熱プログラマー ソフトウェア開発者の幸せな生き方
Chad Fowler
オーム社
売り上げランキング: 12001

ソフトウェア開発者のみならず、あらゆる分野でその道を極めようとしている人におすすめです。プログラマ固有のところは極めて少なく、自分の人生を自分で切り開いていくために必要な情報が分かりやすく整理されています。

以下この本で気になった所を引用しておきます。この本がプログラマ以外の人にも示唆に富む内容であることが伝わるのではないかと。

より良い製品を作って仕事を確保することだけが大切なのではない。より実りある人生を送るためのスキルと感性を磨くことも大切だ。人生には素晴らしいことがたくさんある。仕事はそのひとつに過ぎない。(David Heinemeier Hansson)

偉大になることを望んでいる人のほうが、自分の仕事をこなせれば良いと思っている人よりも、偉大になる可能性がずっと高いからだ。

何かのスペシャリストであると言うことを、単に他のことを知らないという意味で使っている人が多すぎる。

ビジネスの仕組みを知りもしないで、ビジネスが利益を上げるために想像力を働かせて協力できるだろうか?
・・・
想像力を働かせて付加価値を高めるためには、自分が関わるビジネスについての徹底的な理解が必要だ。

本当の意味で何かを習得しようと思ったら、誰かに教えてみることをおすすめする。自分の理解をはっきりした形にする一番いい方法は、自分の言葉を使って、他の人にもわかるように説明することだ。

プロセスを身につけたいなら実践しろ。

いいマネージャの役割は、チームの仕事に優先順位を設定し、チームが仕事をこなすために必要なものを用意し、チームがやる気と生産性を維持出来るように配慮し、最終的に要求を実現することにある。

短く働いた方が、より多くの成果をあげられる。

ソフトウェアの品質が本当の意味で試されるのは、何か問題が起きた時だ。

本当に出来ないときに臆せずに「できません」と言える強さを持ったチームメンバーがいれば、彼らの「できます」という言葉には偽りが無いと確信出来る。

多くのソフトウェア開発者は勘違いしている。事情に通じたマネージャや雇い主なら自分の技能を見ぬいて当然だと思い込んでいるんだ。・・・全部言い訳。彼らは怖がっているだけさ。
誰かが何かすごいことをしても誰もそれを知らなければ何もなかったのと同じだって言うんだ。

大局的に見るなら、作文技術は必要かつ供給不足なんだ。
君ももっと大量の文章を書くことになる。文章を書くことが仕事の一部になるとすれば、もっと作文技術を磨いた方がいい。

君に信念がないと、こういうことはできない。会社の連中が間違った事をするのを傍観していられない。改善の余地があるなら君が変えなければ。

目立つっていうのは、聞かれる前からみんなが君のことを話題にするっていう意味なんだ。

君のキャリアにとって本当に重要なのは昇進でも昇給でも無い。重要なのは、そういう成果を得るために努力した時間だ。もっと重要なのは、そういう成果とは関係ないところで努力した時間だ。

並行コンピューティング技法 第4章 & 第5章

4月 11th, 2010

短いので今週は2章分まとめて読みました。

◯第4章 マルチスレッドアプリケーション設計の8つのルール
・8つのルール

  1. スレッド化設計モデルに加えるべきルール、順不同。
  2. 真に独立した処理を特定する
  3. 並行性はより上位で実装する
  4. コア数増加に備えスケーラビリティ対応を早期に計画する
  5. スレッドセーフなライブラリを使用する
  6. 適切なスレッドモデルを採用する
  7. 実行順序を前提としない
  8. ローカル変数を使用する、できなければロックで保護する
  9. 並行性向上のためのアルゴリズム変更を恐れない

・ルール1: 真に独立した処理を特定する
これが最も重要。 処理が互いに独立していなければ並行実行できない。

・ルール2: 並行性はより上位で実装する
並行性を見つける方法は2種類ある。

  • ボトムアップ
  • トップダウン

どちらを選ぶにせよ、より上位で並行化した方が良い。 アルゴリズムの上位レイヤほど、より多くの独立した処理を含んでいるからである。

・ルール3: コア数増加に備えスケーラビリティ対応を早期に計画する
今後もプロセッサコア数は増加の一途であることが予想される。 開発中のソフトウェアであっても、このことは考慮に入れておくべき。

並行性の設計はタスク分解とデータ分解の2種類があったが、 アプリケーション内の独立した処理とデータサイズではデータサイズの方が増える傾向が強いため、 データ分解設計の方がスケーラビリティーでは有利である。

設計中のソフトウェア/システムが計画している処理能力を十分に達成できても、 将来要求される処理能力は増加する可能性が高い。 処理能力に余裕があれば、処理するデータはまだ誰かが持っている。

・ルール4: スレッドセーフなライブラリを使用する
車輪の再発明は決していい方法ではない。 一般的なライブラリ関数で置換可能であればそれを使うこと。

使用の際には、マニュアルを参照してライブラリがスレッドセーフであるかを必ず確認する。 自作ライブラリなら関数がリエントラントであるように設計する。

・ルール5: 適切なスレッドモデルを採用する
スレッドの明示的な使用(Pthread/Windowsスレッドの直接的な利用)は避けるべき。 抽象化ライブラリ(OpenMP/Intel Threading Building Blocks)を通してスレッドを利用すること。 多くの並行化作業はスレッドを明示的に操作する必要があるほど柔軟性が求められておらず、 実装が複雑になるとバグが入る可能性が高くなる。

開発上の規約などにより、抽象化ライブラリの使用が禁止されている場合でも、 プロトタイプは抽象化ライブラリを使うことで手間を省くことが出来る。

・ルール6: 実行順序を前提としない
スレッドの実行はOSなどのスケジューラで管理されるものであり、 アプリケーション側で順序を決定することは出来ない(非決定性がある)。 スレッドがどんな順序で実行されても正しい結果を返すように設計すること。

また性能の観点から、出来る限りスレッドの実行に制約を課すべきではない。 例えばスレッド処理の待ち合わせをするときは本当に必要か立ち止まって考える必要がある。

・ルール7: ローカル変数を使用する、できなければロックで保護する
同期処理は必要悪だが、最小限の使用に留める必要がある。 共有変数の更新が少ないほど、オーバーヘッドも少なく済む。

まずはスレッドごとに持たせるローカル変数で問題が解決出来ないかを考える。 駄目なら適切なロックを共有データに対して適用する。 デッドロックの温床となるため、1データに対して複数のロックを対応付けてはならない。

・ルール8: 並行性向上のためのアルゴリズム変更を恐れない
逐次処理では最良だったアルゴリズムが、並行処理では最良でないことがある。 並行化出来なかったり、他のアルゴリズムの方が並行化による恩恵を受けやすいことがある。

◯第5章 スレッドライブラリ
・抽象化ライブラリ
スレッドの制御(作成・管理・同期)を抽象化し、プログラマに楽をさせてくれるライブラリ。 スレッドを明示的に作成する処理は無く、柔軟性は落ちる。

・OpenMP
専用のpragma、指示文(ディレクティブ)、環境変数を用いて並行処理可能な部分を指定する。 並行実行コードはコンパイラにより生成される。 並列環境と非並列環境でほぼ同一のソースコードを使用できるという利点がある。

スレッドの管理はfork-joinモデルを採用している。 マスタスレッドが並行処理可能な領域(パラレルリージョン)に到達すると、子スレッドが生成され(fork)、 各スレッドがパラレルリージョンを実行する。 パラレルリージョンの終了時には子スレッドが待ち合わせ(join)、 パラレルリージョン後からメインスレッドが処理を続行する。

・Intelスレッディング・ビルディング・ブロック
並列アルゴリズムが定義、実装、提供されており、 並行処理がカプセル化されたクラスを通して使用する。 商用バージョンとオープンソースバージョンがある。

・明示的スレッドライブラリ
PthreadとWindowsスレッドがある。提供される関数は大差ないはず、必要に応じて調べて使いましょう。

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング
Clay Breshears
オライリージャパン
売り上げランキング: 18712

並行コンピューティング技法 第3章

3月 28th, 2010

少しずつ難しい話も増えてきたかな? 第3章です。

「第3章 正当性の検証と性能測定」

◯第3章で学ぶ内容

  1. 誤りの無い並行アルゴリズムをきちんと設計できたかをどう確認するか
  2. 並行ソースコードが”十分に”並列動作しているかをどう確認するか

◯Ben-Ariの4つの並行実行一般化

  • プログラムとは連続したアトミックな実行文である。
  • 並行プログラムは複数のスレッド内のアトミックな実行文のインタリーブである。
  • アトミックな実行文の全ての組み合わせは、検証する並行アルゴリズムの全ての性質を満たさなければならない。
  • どのインタリーブでもスレッドの実行文が不公平に除外されることはない。

どんなプログラムも最小の実行単位に分けられる。並行処理は”最小の実行単位”が様々な組み合わせで実行される。実装されるアルゴリズム/プログラムはいかなる組み合わせでも正しく実行されなければならない。正しく実行するとは特定の処理が意味もなく除外されないことも含む…ということだと理解しました。

◯クリティカルセクション問題を例にBen-Ariの性質を学ぶ
共有変数を参照/更新するソースコード部分”クリティカルセクション”の実現の方法を通して、Ben-Ariの性質を学ぶ。本では5つの段階を追って解説していますが、ここでは割愛。問題にしたポイントは以下のとおりです。

  • 第1段階:1スレッドがクリティカルリージョンを実行していなくても、もう一方のスレッドがクリティカルリージョンに入ることを禁止されていまう
  • 第2段階:排他制御が保証されないインタリーブの組み合わせがある。
  • 第3段階:デッドロックが発生してしまう
  • 第4段階:一方のスレッドがクリティカルリージョンから除外されてしまう(スターベーション)

ということで、スレッドプログラミングでよく陥りそうな問題が満載です。最終的に第5段階として紹介されているのがデッカーのアルゴリズム – Wikipediaです。でもこのアルゴリズムだと2つのスレッドしか排他制御出来ないので、ランポートのパン屋のアルゴリズム – Wikipediaピーターソンのアルゴリズム – Wikipediaが実用にはいいそうです。でもこの節で学ぶべきは使うアルゴリズムの選択じゃなくて、どういう所に着目して問題を見つけるのかというやり方なので、きちんと学んだことがなければ本を当たった方がいいと思います。

◯デッドロックを発生させる4つの条件
4つの条件はANDで発生する。どれか1つでも成立しなければデッドロックには成り得ない。

  • 相互排除条件:リソースを特定のスレッドがロックしようとするからデッドロックが発生する
  • 獲得後のウェイト:複数のリソースをロックしようとするとデッドロックが起きやすくなる。
  • プリエンプト無し:スレッドが自発的にロックを開放する仕組みが無いからデッドロックが起きると復帰出来ない。
  • 循環待ち:ロックの取得関係が循環になってしまう。

デッドロックを避けるにはどれか1つでも起きないようにすればいいらしいけど、複数リソースのロックとか危ういものは出来るだけ避けた方がいいと思う。

◯並行化によってどれぐらい性能が上がったか?
高速化率はどう伝えるべきか? 筆者いわく倍数がいいとのこと。 105%の高速化率と言っても元より5%速くなっただけかもしれないし、205%の高速かもしれない。2倍といったら受けてが迷うこと無いよね とのこと。確かにその通りかも。

逐次処理を並行処理に置き換えた際にどれぐらい高速化出来るかの見積はアムダールの法則 – Wikipediaグスタフソンの法則 – Wikipediaで出来る。グラフを書いてみると一目瞭然だけど、並行化出来ない処理がたとえ25%でも含まれていると、どんなにコア数を増やしても3倍までしか速くならない。

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング
Clay Breshears
オライリージャパン
売り上げランキング: 3109

実用Git

3月 23rd, 2010
実用Git
実用Git
posted with amazlet at 10.03.23
Jon Loeliger
オライリージャパン
売り上げランキング: 16867
おすすめ度の平均: 3.0

3 翻訳の質が低くて残念

言いたいことは全てAmazonに投稿されている書評で言ってもらった気がします。

翻訳の質が低くて残念です。
すでにgitについてある程度の知識を持っている人でないと、そういったミスリーディングな翻訳文から真の意味をつかむのは難しいと思います。
「入門git」と「入門Git」を制覇して次のステップを目指す人が、翻訳のまずさを自力で補う覚悟のうえで買うのなら、よい本です。

駄目な本かというとそうではなくて、Gitについてこの本より詳しく記述された文章はネットでもないので貴重だと思います。個人的にもgit-svnの使い方が大変勉強になりました。そこだけで3000円ぐらい払っても惜しくないぐらいです。たまに出てくる意味が取りにくい訳がなければ星4つ、O’reilly独特の言い回しが邦訳で取り払われていれば星5つだったと思います。

Gitのオブジェクト管理についてはWEB DB Press Vol.50でも、入門Gitでも紹介されていますが、この本が一番詳しく、説明が丁寧で、わかりやすかったです。Gitをじっくり学びたい人におすすめです。使いたいだけなら入門Gitでいいでしょう。

実用Git 入門git 入門Git WEB+DB PRESS Vol.50

並行コンピューティング技法 第2章

3月 11th, 2010

勉強会の2回目があったのでメモ、1回目は下のリンクからどうぞ。

「第2章 並行か非並行か?それが問題だ」

◯大前提
全ての処理を並列化することは出来ない。世の中には並列化が不可能な処理があり、何がそうなのか知っておく必要がある。並行化できないアルゴリズムは以下が代表例。

  • 状態を持つアルゴリズム
  • 漸化式
  • 帰納変数(ループの度に値が増加する、ループ変数とは1対1に対応しないインデックス)
  • ループ内の処理依存

◯並行アルゴリズムの設計モデル
順序に依存しない処理を並行に実行する「タスク分解」と、大量のデータの個別の部分を並行して処理する「データ分解」がある。
どちらを選んでも基本のフレームワークは変わらない。タスクを準備し、スレッドへ処理を割り当て、次の処理へ進む前に全てのタスクが完了したことを確認する。

◯タスク分解
スレッドに割り当てるタスクを抽出する難易度はソースコードや処理内容に対する理解に反比例する。良く知っていればタスクの抽出も容易になる。タスクを簡単に見つけ出す裏技はないが、処理時間を多く占めるホットスポットにおいて、ループに着目するとそこがタスク抽出に適していることが多い。数値計算もタスク抽出のポイントとしておすすめ。

抽出したタスクの数にもポイントが有る。まずタスクの数はスレッド数(≒コア数)と同じ数以上にする。これはアイドルスレッドを避けるためである。次にタスクの粒度は出来るだけ大きい方が良い。これは並列化によるオーバーヘッドが生じることが影響している。タスクが大きい方がメモリキャッシュが効くなど性能面で有利な点がある。

タスク同士の間には2種類の依存性がある。1つ目は順序の依存で、あるタスクが他のタスクの処理結果に基づいて実行される場合が該当する。2つ目はデータ依存で、変数の使い方で問題が生じることがある。

タスクの割り当ては最初に決めてしまう静的割り当てと、動的にタスクを決める動的割り当てがある。タスクの処理時間が固定の時は静的割り当てが簡単でオーバーヘッドもなくてよい。処理時間にばらつきがある場合は動的にタスクを割り当てる必要がある。

◯データ分解
基本ルールはタスク分解と同じ。分割する数はスレッド数よりも多くする、細かすぎると並列化によるオーバーヘッドが問題になるので大きい粒度で。処理対象となる分割されたデータ領域をチャンクと呼ぶ。チャンク分割はタスクの粒度と境界長の比率が最大になるように分割すると良い。

チャンクの境界において、別チャンクのデータを参照する必要があると工夫がいる。簡単なのは境界部分を予めスレッドごとにコピーしておく方法がある(ゴーストセル)。そうでなければ処理時に必要に応じて参照させる方法があるが、参照対象のデータが未処理の場合、参照処理をまたしておく必要がある。どちらも一長一短がある。

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング
Clay Breshears
オライリージャパン
売り上げランキング: 39727