最初に
本記事は「並列処理」について少し掘り下げた解説記事となります。
プロセスについては→【小ネタ】プロセスってなんだろう?という話
スレッドについては→【小ネタ】スレッドってなんだろう?という話
非同期については→Unity非同期完全に理解するための第一歩~非同期処理とは何か~
並行処理とは?
並行処理とは、複数のプロセスが実行可能状態であることで、実際には同時にプロセスが動いていなくてもユーザー側から任意で切り替えが行えます。人間の目には同時に処理が行われているように見えますが、マルチタスクOSではシングルコアで各プロセスをナノ秒ごとのタイムスライスで区切って高速に切り替えながら1処理ずつ行なっているのです。
並列処理とは?
並列処理とは、計算処理系などの比較的小さくて独立した処理を別々のコアで実行する事で複数コアを持つハードウェアのパフォーマンスを引き出すための手法となります。
この機能を備えているのがUnityであれば「C# Job System」となります。
並列実行ではシステム自体にマルチコアプロセッサが必要となります。つまり、マルチスレッドやマルチプロセスを駆使するアプリを開発したとしてもマルチコアシステムでない場合には並列には実行できません。
で、並列処理と並行処理って結局どう違うの?
並行処理は1つのコアで各プロセスを高速に切り替えて1処理ずつ行なっていると書きましたね。
これに比べて並列処理は実際に複数のコアで同時に処理を行なっていることを指しています。
並行処理では1つのコアに負荷がかかる作業となりますが、並列処理はそれぞれのコアがそれぞれの処理を全力で行うような感じです。
ちなみに非同期は、この二つとは直接的に関係する概念ではありません。非同期はメインスレッドを止めずに別の処理を行うための手法であり、これを実現する方法として並列処理・並行処理どちらもあげることができます。並行の場合は厳密には数ナノ秒程度はメインの処理が止まるかもしれませんが、ユーザーから見たときには停止しているように見えず、別の処理を行えているように見えているため、非同期と言っても良いとされています。
デュアルコアの端末とかは?
PCのデュアルコアと言うのは1個のCPUに2個のコアが存在するため、並列処理が可能です。コア数が二倍になれば、単位時間のうちに二倍の仕事ができるプログラムを組むことで処理速度を二倍にあげられる可能性があります。
その実装方法として、一つは演算器を複数置いて単一命令で並列に計算を行わせる方法です。この方法は複数のデータを並列に処理させるのでデータ並列と呼ばれています。これはSIMD(Single Instruction Multiple Data)と言う種類の命令セットがCPUで提供されているため可能となります。
もう一つの実装方法は、スレッド並列です。これは複数の演算器を起き、各演算器は一つのスレッドを実行します。つまり各スレッドが一つの仕事を担当し、複数のスレッドを並列に実行する方法です。現在の多くのGPUが採用しているSIMT方式は、スレッド並列の実行を行います。
並列プログラムの切り分け方
上から順番に処理を行う(逐次)プログラムのソースから切り出せる処理があるのであれば、それをスレッド(または連携して動作するプロセス)へ割り当てることができます。ただし、アプリケーション内の処理全てが独立しているわけではないので、並列プログラムにも逐次実行部分は残ります。処理をスレッドに割り当てるためには、スレッドを実装したライブラリ等が必要となります。
並列処理の歴史
2005年以降のマルチコアマイクロプロセッサ時代が来た事によって、並列の概念が開発の状況を変えていきました。C++も標準ライブラリに並列プログラミングをサポートする機能を持っています。C++11ではmutex
などの相互排他処理を実現するベース部分の機能が備わっていましたが、C++17から並行並列の新しいSTLが追加されます。 これにより、並列化をコンパイラに丸投げできるようになり、可搬性も上がるようになります。
現代のCPUはパイプライン化されており、複数の命令が同時に「実行中」になることが可能です。また、GPUは本質的に大規模な計算エンジンであるため、幾千もの計算を並列処理で実行することが可能です。CPUのパフォーマンスも改良され、CPUの計算速度はメモリにアクセスするスピードよりもずっと早くなりつつあります。なので現在のCPUはうまいことメモリへのアクセスによって発生するレイテンシを削減するようなことも行なってくれます。
参考
- ゲームエンジンアーキテクチャ(文献)
- GPUを支える技術(文献)
- イケてるエンジニアになろうシリーズ 〜メモリとプロセスとスレッド編〜