読者です 読者をやめる 読者になる 読者になる

tom__bo’s Blog

情報系学生が筋トレしたり、筋トレしたり筋トレしたことを書くブログ。もはやダイアリー

Systems Performance 読んでいく (6章 その1)

Systems Performance: Enterprise and Cloudを読んでいく。

前回の続き。
6章前半部分。

6. CPUs

CPUは全てのソフトウェアを動かしているので、しばしばパフォーマンスの最初のターゲットになる。
特に最近のシステムでは多数のCPUを使い、カーネルによって実行されるソフトウェアで共有されている。

パフォーマンス改善のためにCPUを見る時、高いレベルではプロセスやスレッド、タスクごとの負荷が調べられる。
より低いレベルでは、アプリケーションのコードパスとカーネルが調査される。
そして、最も低いレベルではCPUの命令実行やサイクルの振る舞いが調べられる。

この章では以下の5つが基本的な軸になっている。

  • Background
    • CPUに関連した用語の紹介
    • 基本的なCPUのモデル
    • 主要なCPUのパフォーマンスコンセプト
  • Architecture
  • Methodology
    • 観測と実験の両方の側面からパフォーマンス分析の説明
  • Analysis
    • LinuxSolarisベースシステムの両方のパフォーマンス分析ツールの紹介(Solarisはこのブログでは省略)
  • Tuning
    • チューニング可能な項目の例

前半の3つではCPU分析の基礎について、後半の2性はアプリケーションの実践的な内容について説明していく。

6.1 Terminology

  • Processor
    • 物理的なチップそのもの
    • またはcoreやハードウェアスレッドとして実装されている1つ以上のCPUの実装
  • Core
    • マルチプロセッサにおける独立した1つのCPU
    • 使用方法としてはプロセッサをスケールするために使われ、"chip-level multiprocessing(CMP)"と呼ばれる
  • Hardware thread
  • CPU instruction
    • "instruction set"のうちの1つのCPU操作
    • 算術計算やメモリI/O、ロジックのコントロールなどがある
  • Logical CPU
    • "virtual processor"とも呼ばれる、OSのCPUインスタンス(スケジューリング可能なCPUエンティティ)
    • これはたいてい、ハードウェアスレッドとしてプロセッサに実装されている
  • Scheduler
    • スレッドをCPUに割り当てるカーネルのサブシステム
  • Run queue
    • CPUによって実行されるのを待っているスレッドのキュー

6.2 Model

以下のシンプルなイラストはCPUの基本的な概念を示している。

f:id:tom__bo:20161109120527p:plain

より深い内容は、6.4節で掘り下げていく。

6.2.1 CPU Architecture

上の図は4コアのシングルプロセッサと8ハードウェアスレッドのサンプルである。
これは物理的なアーキテクチャとそれがOSにどう見えているかを示している。
全てのハードウェアスレッドは1つの論理CPUに見えているが、それに加えて、OSにはどの論理CPUが同じコアにあるかもわかっている。

6.2.2 CPU Memory Caches

プロセッサはメモリI/Oパフォーマンスを改善するために様々なハードウェアキャッシュを提供している。
CPUレジスタに近いほど、高速で遠いほど遅いが容量は大きい。

f:id:tom__bo:20161109120540p:plain

6.2.3 CPU Run Queues

下の図はカーネルによってスケジューリングされるCPUの実行キューを示している。
CPUでの実行待ちになっているアプリケーションスレッドはCPUのサチュレーションを示す重要なパフォーマンスメトリクスである。
実行キューで待たされる時間は、"run-queue latency"や"dispatcher-queue latency"と呼ばれるが、ここでは"scheduler latency"と呼ぶことにする。
これは実行キューがキューの構造でないものにも当てはまるからである。(これについては6.4.2を見るように)

マルチプロセッサのCPUでは、カーネルは同じ処理をできるだけ同じCPUで実行しようとする。
これはCPUがデータをキャッシュしやすくするためで、これをCPU affinityと呼ぶ。
NUMAシステムではメモリのレイテンシが改善されている。(これについては7章)
これによってキューイングのためのスレッドの同期処理が避けられる一方で、グローバルにCPUで分散出来るような処理のスケーラビリティが下がる。

6.3 Concepts

以降の内容はCPUのパフォーマンスを見る上で非常に重要なものである。
プロセッサの内部に始まり、CPUのクロックレート、命令がどのように実行されるかがある。 これは後のパフォーマンス分析のバックグラウンドであり、特にcycles-per-instruction(CPI)メトリクスを理解するために重要である。

6.3.1 Clock Rate

クロックは全てのプロセッサロジックを動かしている。 それぞれのCPUは命令を1,2クロックで実行する。 幾つかのCPUでは負荷に合わせてクロックの速度を変えることが出来る。 しかし、クロックが早ければパフォーマンスが改善するとは限らず、CPUがメモリからのデータを待ってストールしているのであれば、CPUのクロックの速度は関係がない。

6.3.2 instruction

CPUの実行命令は以下の命令セットから選ばれる。

  1. Instruction fetch
  2. Instruction decode
  3. Execute
  4. Memory accesses
  5. Register write-back

4と5ははOptionalで、必要が無いこともある。 また、たいてい最も遅いのがメモリへのアクセスで、これは数十サイクルが必要となり、その間はストール命令が入ることになる。それが、キャッシュが重要になる理由である。

6.3.3 Instruction Pipeline

CPUパイプラインは、複数の命令を並列してコンポーネント別に同時に実行する仕組みである。 前にリストした命令ステップが同時に実行されるので、最もうまくいくときは1サイクルで1CPU命令が実行できることになる。

6.3.4 Instruction Width

Instruction Pipelineより更に早く実行することも出来る。複数の関数ユニットは似たような命令を含んでいる。そこで、並列に実行する度合いを上げることでより早く命令を実行することが出来る。これを"super scala"という。

6.3.5 CPI,IPC

Cycle Per Instruction(CPI)はCPUが何処でクロックサイクルを消費しているかを理解する重要な高レベルのメトリクスである。これは(IPC) Instruction Per Cycleで表すこともあるが、単にCPIの逆数である。
CPIが高い状況は、CPUがよくストールしてしまっていることを示し、その場合はCPUのクロックを早くしても効果はなく、メモリのアクセス速度を早くする必要がある。
一方で、これはCPUの最適化なので、CPIが低かろうと、アプリケーションから見て不要な命令をいくら早く実行できてもしょうがないこともある。

6.3.6 Utilization

CPU利用率は、一定のインターバルでCPUインスタンスを計測したときにタスクを実行中だった時間をパーセンタイルで示したものである。 利用率が高いことは必ずしも問題ではない。CPU利用率はしばしばユーザとカーネル時間で分離されて考えられる。

6.3.7 User-Time/Kernel-Time

ユーザレベル、カーネルレベルでの実行時間の比率はアプリケーションの特性を表すことが多い。ユーザレベルの実行時間が多いのは画像処理などのアプリケーションのコードが多く実行されており、I/Oが多いとシステムコールが増えることでカーネルレベルの実行時間が増える。

6.3.8 Saturation

CPUの利用率が100%の状態はサチュレーションを起こしている。 スレッドはスケジューラレイテンシに直面し、システム全体のパフォーマンスは低下しているだろう。
CPUサチュレーションの他の原因は、マルチテナントのクラウド環境におけるCPUリソースコントロールがある。 CPUは100%ではないが、紐付いたホスト側のリソースが一杯になっていることがある。 これがどのように確認できるかは使っているシステムに依存する。

CPUがサチュレーションを起こしているのは、他のリソースタイプと比較すると問題は少ない。プライオリティの高いタスクは現在のスレッドにプリエンプトすることも出来る。

6.3.10 Priority Inversion

プライオリティの逆転は優先度の低いスレッドがリソースのロックを取ることで優先度の高いスレッドがプリエンプトできなくなる現象である。

(例省略)

この問題はSolarisベースのカーネルで"priority inheritance"として解決され、Linuxでも2.6.18からこれをサポートするユーザレベルmutexが提供されている。

6.3.11 Multiprocess, Multithreading

大抵のプロセッサでは複数のCPUを様々な方式で提供している。 CPUをまたいだアプリケーションのスケール方式の違いであるmultiprocess, multithreadingを以下に示す。

f:id:tom__bo:20161109121314p:plain

これらの違いを以下に示す

f:id:tom__bo:20161109121330p:plain

大抵の場合、multithreadingの方が優れているとされるが、デベロッパーにとっての複雑度は増す。

6.3.12 Word Size

プロセッサは最大のワードサイズが32か64bitになるように設計されている。これはintegerのサイズであり、registerのサイズでもある。 ワードサイズはプロセッサに依存し、アドレススペースやデータバスの幅に使われる。

これを大きくすればパフォーマンスが向上するかというと、それほど単純な話ではなく、メモリのオーバーヘッドが増え、型によっては使われないbitが増えてしまうことがある。

6.3.13 Compiler Optimization

アプリケーションのCPU実行はコンパイラオプションによって大きく改善される。 新しいCPU命令セットに対応していたり、最適化が改善するので試す価値はある。

⊂゚U┬───┬~