並列処理のこと、ちょっと覗いてみませんか

# 並列処理むずかしそうだな？

そう思っているのはあなただけかもしれません。

これは、Life is Tech! 東海 のアドベントカレンダー21日目です。

# 並列処理なんてどうでも良くない？

私は大学で並列処理に関する研究をしている大学院生でして、いわば布教記事です。

断定するようですが、**やったことない人は損してます**。せっかくすぐそこにできる環境があるのに。
というか、現代の日本社会で触ったことない人は、ほぼいないと言ってもいいでしょう。

やったことないと思っている人でも知っておいて損はないだろう、ということで、エントリー向けの記事です。

少々厳密性を落としています。さらに、コードはほとんど出てきません。なぜなら日常的にも応用できる話だからです。

未来が透けてみるような、読んでいて負担にならない書きぶりでやらせていただきます。序盤はコンピュータっぽい話はあんまり出てきません。あしからず。

# 並列処理とは、どういうものか

「**並列に**物事を処理する」とは、「同時刻に複数の物事を処理すること」です。

例えばあなたが、「友達 Aさん の結婚式プレゼントに動画を作りたい」、という状況になったとして、その材料として **1000個 の思い出画像や動画**が集まったとしましょう。

それぞれの画像には、「Aさんだけ」「友人とAさん」**「Aさんと元カノ」**「Aさんと今カノ」「風景画像」「短い動画」「長い動画」が写っているものが混在している状況です。

**あぶない。**

画像を振り分けて、あぶないものを選択対象外にしたいです。

あぶないものじゃないものであっても、「ムービーのクライマックスの方は、印象的な画像を置くようにしたい」「長い動画は一部カットしたい」とかもあるかもしれません。

:::note info
**1人で1個1個を順番に**見て、「これどうやって使おうかな」と判断することを「**逐次に**」物事を処理するといいます。

これに対して、**同時に2個以上捌く**ことを、「**並列に**」物事を処理するといいます。
:::

どうやったら同時に2枚以上捌くことができるでしょうか。

# 同時刻に2つ以上のことを行うにはどうするか
残念ながら人間は天才ではないので、2つ以上の物事を同時にこなすことは容易ではありません。

## [案1] 共有記憶型: 知を共有している人に手伝ってもらう
例えば、親友を5人呼び寄せましょう。いい案です。

親友であれば、Aさんの元カレがどんな顔をしているか知ってるはずです。

こうなれば、1000個の動画像を5人で等しく分担して、`1000個 / 5人　= １人あたり　200　個` 。

物事はだいぶ進みやすくなりそうですし、いちいち友人も私に「この人って元カノ？」って聞くことも、ないでしょう。

:::note info
**知を共有しながら**、情報を共有することを「共有記憶」的に処理すると言います
:::

## [案2] メッセージ交換型: 知を共有していない人に手伝ってもらう

一切友人関係でない人に手伝ってもらうこともできるでしょう。

1000人集めることができたら、`1000個 / 1000人 = 1人あたり 1個` 。

親友に限定しないので、人数を集めることは、その気になれば簡単です。

そして一人当たりの負荷はかなり減りますので、ハッピーになれます。

ただ、その1000人は、画像の中に新しい人が出るたびにいちいち「この人って元カノ？」って聞く必要が出て、効率が落ちます。

:::note info
**いちいちコミュニケーションをしながら**、情報を共有することを「メッセージ交換」的に処理すると言います
:::

## [例外案] 一人で頑張ってやってみる
この案は例外的なものです。
1つの答えは、「右目と左目で1枚ずつみる」とかでしょうか。ちょっと早くなるかもしれませんね。
でも、人間の脳は一人につき1つしか(今の所)ありませんので、本質的に並列には処理できません。
せいぜい1.4倍ぐらいの速さでしか処理できないはずです。本当は、目が2つあれば2倍ぐらいになって欲しいですよね。

# どの案がいいだろうか

まあ現実的に考えると、案1の方が楽しそうだし、案2の方は「そんな簡単に人集まらないっすよ〜」っていうのはありますが。

今回は、人間の感情とかは一旦無視して、そして、必要な人数は頑張れば揃う前提で **「処理したいタスクたちをいかにして早く終わらせるか」** ということに注目したいと思います。

これが、それぞれいい点悪い点を列挙した表です。

<table>
<thead>
<tr>
<th>種類</th><th>✅ 良い点</th><th>❌ 悪い点</th>
</tr>
</thead>
<tbody>
<tr>
<td>共有記憶型</td><td>自分の好きなタイミングで好きな処理ができる</td><td>人を増やし辛い</td>
</tr>
<tr>
<td>メッセージ交換型</td><td>人を増やし易い</td><td>いちいち他人の作業に割り込んで聞かなきゃいけないから効率が落ちる</td>
</tr>
</tbody>
</table>

実際のところ、このどっちがいいのか、というのは、時と場合によるかもしれません。

あえて選び方を示すならば、大規模に物事を用意できない場合（数人グループで物事をやる場合）には、共有記憶型になりがちかなと思います。

# コンピュータの仕組みに置き換えると、どういうことになるの？

ここまでは、比較的日常的な話題を取り扱いましたが、実際、コンピュータでも同じような考え方もします。

みなさんのPCに搭載されているCPUは、だいたい2つ以上の演算コア（クアッドコアとか聞いたことがある方もいらっしゃるかもです）を持っています。**コアと言うのは、超簡単に言うと、人間一人が持つ頭脳のようなものです。**

ここまで読んだ方には伝わると思いますが、あなたの目の前にあるPCには **「親友が揃っている」** ようなものです。

揃っているのに、有効に使わないわけにはいかないでしょう。

**しかしながら、普段はその親友たちを、全くの赤の他人のように使っているんです。**

ブラウザ・コードエディタ・メールと多数の仕事を、コアに分散して実行していますが、これらは赤の他人でもできる仕事内容です。

しかし、本来的には、せっかく親友が集まっているなら、その親密度を有効活用したいわけです。

そんな場合には、「マルチスレッド処理」と検索してみましょう。一般的には POSIXスレッド を利用したり、後は少し踏み込むならば、C言語でOpenMPというライブラリを使うと、これを実現できます。 **あなたの持っているPCで、なんと、並列処理、できちゃうんですよ！**

逆に、「うちの家、PCが1000台あるんです〜」っていう、**逸般の誤家庭** に住んでいる人は、ぜひメッセージ交換型のプログラミングにチャレンジして、超高並列プログラミングをしてみましょう（1000台なくても、2台からでもできます）！ 「MPI」と検索してみると、なにやら面白そうな世界が広がっていますよ〜。

# まだまだ面白いことあるんですよ

大事なことをここで言及しておきたいです。

:::note info
**チームマネジメントに対しても、コンピュータの並列処理で研究されているエッセンスは、大変有効活用できます。**
:::

以下に、もっと面白いこと、書いてますんで、よかったら読んでいってくださいませ。

## Affinity
コンピュータの世界では、「Affinity」と言うワードが(ハイパフォーマンスコンピューティングになると)出てきたりします。

これは先ほどまで言っていたような、「友人との親しさの度合い」に近いものと捉えることが可能です。

**なるべく、情報交換のコストがかからないように、コミュニケーションがさっとできる人同士でチーム編成をしたり、近くで作業させたいですよね。**

Affinityを意識してプログラミングするのは、作業者側にとってはすごく大変です。なぜなら今目の前にあるタスクでかかりきりなのですから。

チームリーダーであっても、誰にどう言うふうにタスクをアサインすると、より効率的になるか、と言うのは腕が必要ですね。

これを自動化しましょう、と言うことも考えたりしてるんです〜。すごいこと考えますよね。


## ロードバランシング
先ほどの「元カレを取り除く」例で言うと、動画像が1000個がある状態でしたね。

仮に100人集めることができて、`一人当たり10個担当する`ことになったとします。

**全員が「よーい、どん！」で開始したとしても、残念ながら全員が同時に終わるとは限りません。**

だって、中には動画もあるし。

一枚に1000人が写ってる場合、その画像の中に元カレいるかどうか、ちゃんとチェックしないといけないですから。

そんな時には、 **「ロードバランシング」** と言うものを行うと、良いと言われています。

これもまー、面白い世界です。他の人にいい感じにタスクを割り振って、全員が等しく仕事を終えたい、と言うのは、日常的にもありますよね。誰か一人がずっと苦労するのは、良くないですから。

## ネットワークトポロジ
いわゆるスパコンというのが、一台のくせに超高いのは、これが原因と言われています。

「あの人に話を聞きたい」となったとき、必ず仲介役の人を何人も介さないと話を聞けない、となると、その仲介役が忙しそうにしていれば、すぐに話を聞くことができません。

できれば、それぞれの人と直接話せるような状態が望ましいわけです。

コンピュータは他のコンピュータとの通信をダイレクトにしたいなら、共用のケーブルを使うのではなく、専用のケーブルと回路が欲しいものです。

しかしながら、**1000人のチームを作れば、1台につき1000本の入力口が必要** なわけです。それは、ちょっと難しそう、と思っていただけるのではないでしょうか。

なんとか工夫して、それに近いことを実現させよう、と必死に考えて作ってる人もいます。

そして、そういうふうに作られたマシンを、効率的に活用するソフトウェア基盤に力を注いでいる人もいます。

## 超高速インターコネクト

あとは、そもそも **「コミュニケーションで会話するスピードをめっちゃ早くしたろ！」** っていうことを考えている人もいます。

しかし、超高速な会話を実現するというのは、難しいものです。

うるさい環境であれば、ゆっくり話したり、何回も復唱したりしないといけなかったり（再送制御とか輻輳制御とか言ったりします）。

専用の会話ルールを開発したり（例えば「お疲れ様です！」を「うす！」と言えば、会話は高速になりますよね）。

いろんな人が簡単に使えるような会話を実現するというのは、まー、難しいです。

現状だと比較的 TCP/IP はみんな簡単におしゃべりできるのですが、もっと早く喋れる仕組みが欲しい!、と考えて取り組んでる人もたくさんいるのです。


# Welcome to 並列処理!

ここまで読んだあなたは、もう並列処理について、虜になっているでしょう。

コンピュータの研究者の中には、このようなことを超真面目に考えている人もたくさんいます。私もその一人です。

**コンピュータのくせに、意外と「人間的」なことをしているものです。**

こう言うこと考えるの好きな人は、ぜひ、大学の「情報工学科」の門をたたいてみてください。おもろい世界とおもろい人がたくさん待ってますよ。