KEIS BLOGは株式会社ケイズ・ソフトウェアが運営しています。

KEIS BLOG

並列実行数をふやせば増やすほどパフォーマンスが上がるわけでも無い理由

コンピュータのパフォーマンスを最大限に引き出すために、昨今のメニーコア時代、並列実行(マルチスレッドやマルチプロセス)の活用が一般的だと思います。でも、並列実行数を増やせば必ずしもパフォーマンスが向上するわけではありません。

「こんな並列数にしたらかえってパフォーマンス落ちるけど・・」って思うことがあるんで、この記事では、並列実行数を増やすことが必ずしも望ましい結果をもたらさない理由について解説してみようと思います。

目次


並列実行の基本

複数のタスクを同時に実行することで、全体の処理時間を短縮する手法ですね。マルチコアCPUの登場以降、並列処理は不可欠なわけですが。でも、並列実行数を無制限に増やせば良いというわけではなく、以下のような理由からパフォーマンス向上に限界があります。

リソースの競合

複数のタスクが同時に実行されると、CPU、メモリ、I/Oなどのシステムリソースを共有します。並列実行数が増えると、これらのリソースへのアクセス競合が発生し、逆に処理速度が低下することがあります。

オーバーヘッドの増加

並列処理を管理するためには、スレッドやプロセスの生成、同期、通信などにオーバーヘッドが発生します。並列実行数が増えると、これらのオーバーヘッドも増加し、総合的なパフォーマンスに悪影響を与えることがあります。

Amdahlの法則

Amdahlの法則は、並列処理による性能向上の限界を示す理論です。法則によれば、プログラムの中で並列化できる部分の割合が性能向上の上限を決定します。例えば、プログラムの90%が並列化可能であっても、並列実行数を無限に増やしても、理論的な最大性能向上は約10倍に限られます。

スケーラビリティの限界

ソフトウェアやアルゴリズム自体にスケーラビリティの限界が存在します。特定のタスクやアルゴリズムは、並列化に適していない場合があり、並列実行数を増やしても性能が向上しない、または低下することがあります。

実際の例

じゃ、具体的な例を通じて、並列実行数を増やしてもパフォーマンスが上がらない理由を見てみましょう。

例1: CPUリソースの競合

例えば、シングルコアCPU上で複数のプロセスを実行すると、各プロセスがCPU時間を奪い合うんで、並列実行数を増やすほど、各プロセスに割り当てられるCPU時間が減少して、総合的な処理速度が低下します。

#!/bin/bash
# CPU負荷をかけるスクリプト
for i in {1..100}; do
  while :; do :; done &
done
wait

上記のスクリプトでは、無限ループを100個並列実行します。シングルコアCPUでこれを動かすと、これらのプロセスがCPU時間を奪い合うため、全体のパフォーマンスが著しく低下します。

例2: I/Oリソースのボトルネック

ディスクやネットワークなどのI/Oリソースを多用するタスクでも、並列実行数を増やしすぎると、I/O待ちが増加し、全体のパフォーマンスが低下します。例えば、大量のファイルを同時に読み書きすると、ディスクのヘッドが頻繁に移動し、アクセス速度が低下します。(程度の差はありますがSSDでもこれは起きます)

# 並列でファイルを読み込むスクリプト
for file in *.log; do
  cat "$file" > /dev/null &
done
wait

このスクリプトでは、ログファイルを並列に読み込みますが、並列実行数がディスクの性能を超えると、I/O待ちが増加し、処理全体の速度が低下します。

まとめ

並列実行数を増やすことで、パフォーマンスが向上する場合がありますが、実際には以下の理由から必ずしもそうではないってことです:

  • システムリソースの競合によるパフォーマンス低下
  • 並列処理の管理に伴うオーバーヘッドの増加
  • Amdahlの法則による理論的な性能向上の限界
  • ソフトウェアやアルゴリズムのスケーラビリティの限界

最適な並列実行数を見極めるためには、システムのリソースやタスクの特性を理解し、適切なバランスを取ることが重要です。過剰な並列化は逆効果!、性能向上を目指す際は慎重に検討しましょう。


参考資料