谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

並列処理を使って、計算効率よりスループットを重視する

世の中のCPUは、クロック数からマルチコアの方向に進んでいます。
10年前とは違い、いまでは自作する人でも「自分のPCのCPUクロック数」を思い出せなくなりました。
でも、さすがにCPUのコア数は、思い出せないなんてことはありません。

CPUは100コア時代に向けて猛進している。IntelAMDなど大手CPUメーカーの技術リーダーを始め、多くのCPU業界関係者がそう語っている。すでにCPUメーカーにとっては、100コアは規定の路線のようだ。

2010年代の100コアCPU時代に向けて走るCPUメーカー - PC Watch

どうやら、次の10年は、100コアを目指して進むようです。


こうなってくると、当然、プログラミングモデルも変わってくるはずです。
特に「並列処理」について、考え直す必要がでてくるでしょう。


処理は、以下の3つに分類されていくんじゃないかと思います。

  • 並列に実行できる処理
  • 並列に実行できない処理
  • 厳密には並列に実行できないけど、スループット向上のため、並列化させる処理

3つ目の処理は、何を言ってるのか分からないかも知れないので、
順を追って説明していきます。


たとえば、以下のような処理を考えます。
1. リクエストを受け付ける
2. リクエストを受けたことをログ出力する
3. いくつかのテーブルから検索する
4. 検索結果をマージする
5. 検索結果をソートする
6. ソートしたデータに連番を振る
7. データをテーブルに挿入する
8. 処理が完了した旨をメールで通知する
9. 処理が完了した旨をログ出力する


普通にJavaで書いちゃうと、これらを1スレッドで(直列に)処理するかも知れません。
では、このうち、どこが並列に処理できるか考えていきましょう。


まず、ログ出力やメールでの通知なんかは、別スレッドで行っても構いません。
そう、「2.」と「3.以降」は、並列して行うことができます。
さらに、「2.」と「7.」が完了した時点で、「8.」と「9.」は並列に実行できます。
また、「3.」の検索も、検索条件によっては並列実行できるでしょう。


まだあります。
「6.」「7.」の連番を振って挿入するところも、
データをいくつかのブロックに分けてしまえば、
ブロックごとに担当するCPUを割り当てて、
「連番を振って挿入する」という処理を、同時に実行できるでしょう。


、、、この辺りまでは、これまでのプログラミングモデルでも考える範囲だと思います。


でも、
「厳密には並列に実行できないけど、スループット向上のため、並列化させる処理」
という考え方を導入すると、(データ量によっては)まだ並列処理すべき箇所が見つかります。


たとえばソートです。
計算効率を考えれば、全部のデータが揃ってから、ソートを開始するでしょう。


でも、もしソートに時間が掛かるような場合、
「検索でデータを受け取りつつ、とりあえず受け取ったデータをソートし始める」
としてみては、どうでしょうか。


こうすれば、計算に無駄が発生する一方で、
検索が完了した時点で、ある程度はデータがソートされているため、
そこからソートが完了するまでの時間を、短縮することができるはずです。
データのマージなども、同様です。


今後、CPUのコア数が増えていくに従って、
こういう「ちょっとした計算の無駄」を被ってでも、「CPUの空き時間を使って」、
スループットを上げるようなモデルが、流行ってくるんじゃないでしょうか。


僕は並列処理などあんまり考えたことがない素人なので、
既に確立した技術論などがあるのを、知らないだけかもしれません。


今後、プログラミングで食っていくのであれば、
そういう所の勉強を、おろそかにはできないな、と思います。