Go言語100Tips ありがちなミスを把握し、実装を最適化する の No.56を読んだ。ここから第8章 並行処理 の続き。
No.56 では、ゴルーチンを使って処理を並行に実行した場合、速くならない場合があることを説明している。これは、並行処理がどのようにOSでスケジューリングされ、実行されるか、ということを理解する必要がある。
CPUコアが実行するOSスレッドはあるスレッドから別スレッドに切り替わる時、コンテキストスイッチ(context switching)を行うが、これはコストが高い操作とみなされている。
小さい処理をたくさん処理するためにゴルーチンを生成すると、このコンテキストスイッチの負荷の方が高くなってしまい、並列処理の利点が得られなくなる場合がある。
最近のCPUは、逐次的なコードや予測可能なコードの実行が驚くほど効率的になっているので、むやみに並行処理を書いても、並列性の効果が得られないばかりか、遅くなってしまう場合がある。そして、この並行処理は物事を複雑にしてしまう。
並列バージョンの方が速いという確信が持てない場合、単純な逐次バージョンから始めて、プロファイリングやベンチマークなどを使って並行処理を使う価値があるかどうか確認した方が良い、とのこと。
並列処理が遅くなるパターンとして、コンテキストスイッチコストが書かれていたが、このほかにも、シングルコア、同期処理、ブロッキング処理などが原因で期待したほど速くない場合があったと思う。Goではベンチマークのテストコードを書くことができるので、気になったらすぐにこれを試すのは良いと思う。