35
1 FlexSC-Threadsの紹介 プログラムの変更無しに マルチスレッドプロセスを高速化 V0.9.4 2015/10/27 Satoru Takeuchi <[email protected]>

FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

Embed Size (px)

Citation preview

Page 1: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

1

FlexSC-Threadsの紹介プログラムの変更無しに

マルチスレッドプロセスを高速化V0.9.4

2015/10/27Satoru Takeuchi

<[email protected]>

Page 2: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

2

はじめに● 本書の目的

● “FlexSC: Flexible System Call Scheduling withException-Less System Calls”[1]という論文に記載されているFlexSC-Threadsの紹介

● 執筆動機● FlexSC-Threadsは機能の効果、実装ともにかっこいいので、多くの人に知ってもらいたかった

● 元論文を読むのに必要なOS、とくにスケジューラ)の知識が無くても読める、副読本を作りたかった

Page 3: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

3

注意点● 本書に記載の数値やグラフは単純化してある

● 正確なところを知りたければ、元論文を参照してほしい

● 元論文以上の知識は得られないので、元論文を最初から理解できるような人は対象外

● 本書の中に記載されている「性能」とは、とくに断りがなければCPUのInstrction per secondのこと

Page 4: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

4

目次1.FlexSC-Threadsとは2.前提知識3.動作のしくみ4.実装5.まとめ6.参考文献

Page 5: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

5

FlexSC-Threadsとは: 概要● Linuxのマルチスレッドプロセスを高速化するpthread互換ライブラリ

● 使い方: pthreadライブラリとしてFlexSC-Threadsをリンク

● プログラムの変更は不要

Page 6: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

6

FlexSC-Threadsとは: 効果と適用範囲

● 性能向上の例● Apache: 116%Up● MySQL: 40%Up● BIND: 105%Up

● 性能向上が見込める条件● スレッド数が多い● システムコールの呼び出し頻度が高い

Page 7: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

7

FlexSC-Threadsとは: 着想● 後述の、ユーザモードとカーネルモードの間の状態遷移(以下、状態遷移と記載)の数を極力減らすことによって性能向上を図る1.状態遷移の頻度が減少2.キャッシュフラッシュの頻度減少3.キャッシュヒット率向上4.性能向上

Page 8: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

8

FlexSC-Threadsとは: 現在の状況● glibcに実装しようとした計画もかつては存在

● その後音沙汰が無いので、立ち消えになった模様

● 自前で実装してみた人もいるらしい[2]● 筆者は動作確認をしていないため、まともに動くかどうかは不明

Page 9: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

9

前提知識(1/3): システムコール発行時の状態遷移

● プロセスがシステムコールを発行するたびに状態遷移が2回発生

ユーザモード

カーネルモード

状態遷移

ユーザのためのシステムコールを処理

カーネルから割り当てられた一部システムリソースしか使えない

システムリソースを全て利用可能

Page 10: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

10

前提知識(1/3): キャッシュメモリのフラッシュ

● 状態遷移のたびにキャッシュメモリがフラッシュされる

ユーザモード

カーネルモード

キャッシュのフラッシュ

キャッシュのフラッシュ

Page 11: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

11

前提知識(1/3): キャッシュフラッシュの悪影響

● キャッシュフラッシュからしばらくキャッシュヒット率が下がるため、性能劣化

性能

システムコール発行からの経過時間

トータルでは斜線部分の面積だけ性能劣化

Page 12: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

12

前提知識(1/3): 短時間に多くのシステムコールを発行した場合

● 低い性能のまま時間が経過

性能(単位時間あたりの

命令実行数)

経過時間

ユーザモード

カーネルモード

トータルでは斜線部分の面積だけ性能劣化

Page 13: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

13

前提知識(2/3): スレッドモデル● スレッドを実装する方法

● 1x1モデル: スレッドとカーネル内のスケジューリング対象が1:1に対応

● glibcのデフォルトpthreadライブラリ(NPTL)はこれ

● Mx1モデル: 同、M(スレッド数):1に対応● 1CPUのFlexSC-Threadsはこれ

● MxNモデル: 同、MxNに対応● 複数CPUのFlexSC-Threadsはこれ

● どれも一長一短● 以降、1x1とMx1について図解説明

Page 14: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

14

前提知識(2/3): 時分割によるプロセスの並行処理

● 1CPU上に複数プロセスが存在する場合、各プロセスが一定時間ごとに、順番にCPUを使用

● 例) p1, p2, p3の3つのプロセスが存在● 全プロセスがCPUを使う処理のみ実行

CPU上で動作中の処理

時刻経過

p1 p2 p3 p1 p2

Page 15: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

15

前提知識(2/3): 並行処理時の状態遷移

● 実はCPU上で動作するプロセスが変化するたびに状態遷移が起き、カーネル上のスケジューラという処理が動作(*1)

● スケジューラは次にどのプロセスを動かすかを決定(詳細は割愛)

● そのたび性能劣化CPU上で動作

中の処理

カーネルモード

p1

ユーザモード

p2 p3 p1 p2

時刻経過

*1) 簡単のため、個々のタイマ割り込みによる状態遷移は無視

Page 16: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

16

前提知識(2/3): 1x1モデルにおけるスレッドの並行処理

● 例) 3スレッドt1, t2, t3が存在する場合● 全スレッドがCPUを使う処理のみ実行

●結果は複数プロセスが存在する場合と同じ● そのたびに性能劣化

CPU上で動作中の処理

カーネルモード

t1

ユーザモード

t2 t3 t1 t2

時刻経過

Page 17: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

17

前提知識(2/3): Mx1モデルにおけるスレッドの並行処理

● 例) 3スレッドt1, t2, t3が存在する場合● 全スレッドがCPUを使う処理のみ実行

● CPU上で別スレッドが動き出す際に状態遷移が発生しない

● 理由: Mx1モデルはユーザ空間でスレッドのスケジューリングをしている

CPU上で動作中の処理

カーネルモード

t2

ユーザモード

時刻経過

t1 t3 t1 t2

Page 18: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

18

前提知識(3/3): システムコールのラッパ関数

●通常、システムコールはlibcのラッパ関数を介して呼び出す

●直接呼び出すにはアセンブリ言語を使う必要があり、移植性が無い

ユーザプロセス

直接呼び出し移植性なし

アーキテクチャ依存アセンブリ言語で書く

libcのラッパ関数呼び出しCで書く

libc経由で呼び出し移植性あり

アーキテクチャ依存アセンブリ言語で書く

libcのラッパ関数

Page 19: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

19

動作のしくみ: 前置き●簡単のため、1CPUの場合について説明● 複数CPUの場合でも基本的には同じ

● ここでいう複数CPUとは、複数コア、複数スレッドの場合も含む

Page 20: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

20

動作のしくみ: NPTLにおける複数スレッドの動作

● スレッドモデルは1x1● 例) 複数スレッドt1, t2, t3がCPU上で動作するたびにシステムコールを発行

●簡単のため、システムコールがブロックされる場合は考えない

●大量の状態遷移が発生CPU上で動作

中の処理

カーネルモード(スケジューラ)

ユーザモード

時刻経過

t1

カーネルモード(システムコール処理)

t1 t2t2 t3t3 t1t1

Page 21: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

21

動作のしくみ: FlexSC-Threads

● Mx1スレッドモデル● システムコール発行時の処理が以下のように変わる1.各スレッドのシステムコール要求を一旦溜めておく

2.所定のタイミング(後述)で、システムコールを連続実行

Page 22: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

22

動作のしくみ: FlexSC-Threadsにおける複数スレッドの動作

● 例) 複数スレッドt1, t2, t3がCPU上で動作するたびにシステムコールを発行

● 状態遷移の数が激減することによって性能向上● Mx1モデルなので、CPU上で動作するスレッドが変わっても状態遷移無し

● システムコールの発行は3回に1回で済むCPU上で動作

中の処理

カーネルモード(スケジューラ)

ユーザモード

時刻経過

カーネルモード(システムコール処理)

t1 t2 t3 t1 t2 t3 t1 t2 t3

t1, t2, t3用のシステムコールを連続実行

Page 23: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

23

動作のしくみ: 複数CPUの場合● 全CPUに同じ処理が並ぶだけ(図は2CPUの場合)

● カーネル処理がCPUの数存在するので、スレッドモデルはM(スレッド数)xN(CPU数)

CPU2上で動作中の処理

カーネルモード(スケジューラ)

ユーザモード

時刻経過

カーネルモード(システムコール処理)

t4 t5 t6 t4 t5 t6 t4 t5 t6

CPU1上で動作中の処理 t1 t2 t3 t1 t2 t3 t1 t2 t3

Page 24: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

24

動作のしくみ: さらなる性能向上● スレッドがn本あれば、n回のシステムコール発行につき2回だけ状態遷移

● スレッド数が多くなるほど、システムコール呼び出し頻度が高くなるほど、システムコールを連続実行できる頻度が向上し、さらなる性能向上が期待できる

Page 25: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

25

実装: 概要● 前述のしくみを実現するために、以下の作り込みが必要

● カーネル: 新規システムコールの追加● 初期化用● システムコールの連続実行用(以下、連続実行用と記載)

● FlexSC-Threads: 新規作成● ロード時に初期化用システムコールを呼び出す

● システムコールのラッパ関数● pthreadライブラリ関数

Page 26: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

26

実装: 初期化用システムコール●連続実行用システムコールを使用可能にする

1.ユーザとカーネルの共有メモリを作成し、前述のキューとして使用

● キュー内エントリのデータ構造● システムコール実行に必要なパラメタ● システムコールの終了状態●戻り値

2.プロセスにキューのアドレスを返す

Page 27: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

27

実装: 連続実行用システムコール1.キューから取り出した全エントリについて、以下の処理を実行1.1.システムコールを実行1.2.実行したシステムコールの戻り値を、該当するキューのエントリに書き込む

1.3.終了状態を更新2.キューが空になったらユーザモードに復帰

Page 28: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

28

実装: システムコールのラッパ関数キューにシステムコールのパラメタを書いたエントリを挿入

キューが一杯?

連続実行用システムコールを呼び出す

他に実行可能なスレッドが存在?

他のスレッドにCPU実行権を明け渡す

自身の戻り値を必要箇所に書き込んだ上で次の処理に進む

システムコールが完了済のスレッドを全て起こす

他のスレッドのシステムコールが

完了済?

YesNo

No

Yes

No

Yes

Page 29: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

29

実装: pthreadライブラリ関数● カーネルの助け無しに、ライブラリ内だけでスレッド制御の仕組みを作成

● 理由: スレッドモデルがMx1

Page 30: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

30

実装: FlexSC-Threadsの動的リンク● 動的リンクをすれば準備完了

●連続実行用システムコールが使用可能になる● libc提供のラッパ関数を上書き● pthreadライブラリ関数を上書き

● プログラムのバイナリ変更は不要● 以下の場合はFlexSC-Threadsの恩恵を受けられない

● libcを静的リンクしている● libc提供のラッパ関数経由でシステムコールを呼んでいない

Page 31: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

31

複数CPUの場合● キューとカーネル処理がCPUごとに存在するだけで、後は1CPUの場合と一緒

● キューがCPUごとに存在するため、排他制御は不要

● スケーラビリティあり

Page 32: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

32

まとめ: ユーザから見た変化● libcのインターフェイスは全く変更が無いため、プログラムは変更不要

● スレッドモデルの変更に伴い/proc/<pid>/以下の見え方が変わるため、そこに依存するような処理をしている場合には考慮が必要

● スレッドライブラリの入れ替えだけで性能向上● システム標準のlibc(通常glibc)が対応していれば、環境変数の設定など、より簡単な方法でFlexSC-Threadsを使用できるようになるかも

Page 33: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

33

まとめ: 使用するにあたって● システムコールの発行数が少ない or スレッド数が少ない場合、期待に反して性能劣化する可能性あり

● とくにシングルスレッドの場合、システムコール発行毎に連続実行用システムコールを発行するため、使う意味がない

● 使用可否の判断をする前の性能実測が必須

Page 34: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

34

まとめ: 個人的な感想● レイテンシの最悪値/中央値/最良値も見てみたい

● 元論文中にはスループットと平均レイテンシについての情報のみ

●個々のレイテンシを重要視するようなシステムにも適用できるか否かを確認したい

●原理的には他のOSでも実装可能なので、やってみると面白いかも

Page 35: FlexSC-Threadsの紹介 -プログラムの変更無しにマルチスレッドプロセスを高速化

35

参考文献1.Livio Soares and Michael Stumm. FlexSC:Flexible System Call Scheduling with Exception-Less System Calls

http://www.cs.cmu.edu/~chensm/Big_Data_reading_group/papers/flexsc-osdi10.pdf

2.Github ID “spinlock”. implements flexsc(flexiable system call, OSDI '10) on ubuntuhttps://github.com/spinlock/flexsc