技術メモ

技術メモ

パイプで並列処理

はじめに

Software Design 2012年8月号」の「開眼シェルスクリプト」の焼き直し。
Webにあるので一読することを勧める。
開眼シェルスクリプト2012年8月号 – 上田ブログ

パイプ

パイプにつなげたコマンドは並列稼働する(複数のCPUをなるたけ休まず働かせようとする)。
複数のCPUが、パイプで連結された各コマンドの動作/停止を高速に切り替えることで、
加工データをバケツリレー形式で前から後ろへ送っていく。
CPUの数に応じて効果の度合いは変動するものの、コマンドを細かく分割するほうが、時間当たりの処理量が増える。

並列化されていることは、以下のようにして確認できる。

  • timeコマンドの結果、「user > real」となっている(1個のCPUでは「実際に掛かった待ち時間」よりもCPU時間の方が長くなることはない、基本的に「user + sys = real」)。
    ※正確な処理時間を測る場合は、繰り返し計測を行い、統計情報(平均値とばらつきの傾向等)を求める必要がある

  • topコマンドの結果、対象コマンド(パイプより連結された複数のコマンド)のCPU使用率が100%を超えている(例えば、計150%であれば、1.5個分のCPUを使用しているといえる)。

並列化の限界

パイプでつながれたコマンドが並列実行されるのは、データが滞りなく流れている時のみ。
パイプ前後のコマンドがデータの受け取りに手間取っている場合には、思いのほか並列実行の恩恵が受けれない。

事例として次のようなものが挙げられる。

  • 負荷にばらつきがある場合、一番負荷の高いコマンドの処理時間以上に処理が早く終わることはない
    例えば、grepの検索結果をawkで処理する(grepの処理するデータ量がawkの処理するデータ量よりも多い)場合、grep側の処理が終わるのを待つ必要がある。

  • データをブロックするコマンドがある場合、そのコマンドがボトルネックになる
    例えば、sortコマンドは全データを読み込まないと結果を出力できないため、sortコマンドをパイプでつなげた場合、sortが終わるまで後続の処理は実行されない。
    対応としては、sortコマンドの位置をできるだけ後ろに回す、またはsortコマンドの処理するデータ量を減らすことで処理効率を上げる。