• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Intel TSX HLE を触ってみた x86opti
 

Intel TSX HLE を触ってみた x86opti

on

  • 2,826 views

Intel TSX HLE の可能性を探るべく,いくつかのマイクロベンチマークで性能評価した.

Intel TSX HLE の可能性を探るべく,いくつかのマイクロベンチマークで性能評価した.

Statistics

Views

Total Views
2,826
Views on SlideShare
1,755
Embed Views
1,071

Actions

Likes
7
Downloads
21
Comments
0

3 Embeds 1,071

https://bozuman.cybozu.com 744
https://twitter.com 273
https://bozuman.s.cybozu.com 54

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Intel TSX HLE を触ってみた x86opti Intel TSX HLE を触ってみた x86opti Presentation Transcript

    • Intel TSX HLE を触ってみた x86/x64最適化勉強会6 2013-08-31 星野喬@サイボウズ・ラボ / @starpoz 1
    • 自己紹介 •  星野 喬(@starpoz) –  サイボウズ・ラボ •  興味 –  データベース,ストレージ,分散アルゴリズムなど •  今の仕事: #walbdev –  Linux における block device の効率的な 増分記録ドライバ •  http://developer.cybozu.co.jp/tech/?p=5130‎ 2
    • 今日の話 •  Intel の最新 CPU (Haswell) の 新機能のひとつ TSX HLE を使い 性能評価をしてみて トランザクショナルメモリの可能性を探る •  後追い実験大歓迎 J 3
    • トランザクショナルメモリ (TM) •  「Intel TSX について」参照 –  http://www.slideshare.net/starpos/intel-tsxx86opti4 •  要約: atomic メモリアクセスを実現する技術 –  他と競合したくない一連のメモリアクセス –  Lock-free な時代がすぐそこに(反論アリ 4
    • Intel TSX •  Transactional Synchronization eXtension •  2 つのインターフェースを提供 –  HLE: Lock prefix の拡張で細粒度の排他を実現 –  RTM: 制約はあるが HardwareTM そのもの •  楽観的な振舞 •  CPU L1 キャッシュ上で必要なデータを管理 •  キャッシュライン単位での競合検出 5
    • 競合 (collision) •  あるリソースへの複数主体からのアクセスが 同時に起きること(要出典) •  Intel TSX の場合: –  リソース: キャッシュライン単位のメモリ領域 –  主体: スレッド –  アクセス: read/write (全て read の場合を除く) –  同時: クリティカルセクションの実行期間が重複 6
    • HLE: Hardware Lock Elision 競合発生しないケース 競合発生するケース 時間 ロックを無視して 投機実行開始 競合発生しなかった めでたしめでたし 時間 競合発生 ロック取れたので 変更破棄 必ず実行できる ロック待ち体制 •  楽観的挙動 –(失敗)à 悲観的挙動 •  失敗すると電気代が無駄になる 7
    • Spinlock with HLE •  GCC 4.8 の場合 (マニュアル参照) class SpinlockHle { private: char &lock_; public: explicit SpinlockHle(char &lock) : lock_(lock) { int flags = __ATOMIC_ACQUIRE | __ATOMIC_HLE_ACQUIRE; while (__atomic_exchange_n(&lock_, 1, flags)) _mm_pause(); } ~SpinlockHle() noexcept { int flags = __ATOMIC_RELEASE | __ATOMIC_HLE_RELEASE; __atomic_clear(&lock_, flags); } }; 8
    • HLE on/off の違い --- t1.hle0.s 2013-08-31 09:23:58.000000000 +0900 +++ t1.hle1.s 2013-08-31 09:23:30.000000000 +0900 @@ -13,12 +13,12 @@ .L3: rep nop .L2: movl %edx, %eax xchgb -1(%rsp), %al + xacquire xchgb -1(%rsp), %al testb %al, %al jne .L3 movb $0, -1(%rsp) + xrelease movb $0, -1(%rsp) xorl %eax, %eax ret .cfi_endproc .LFE859: 9
    • 実験環境 •  CPU: Core i7-4770 –  4cores 8HT –  HT 有効 –  TurboBoost 有効 •  メモリ: 16GB •  OS: Ubuntu 13.04 x86_64 kernel 3.8.19 •  コンパイラ: GCC 4.8.1 –  最適化フラグ: -O2 のみ 10
    • 実験方法 •  スレッドを必要なだけ起動して,X 秒間クリティカル セクション (CS) を繰り返し実行 •  Spinlock を使って CS の排他を取る –  HLE 有効/無効は実験パラメータ –  終了判定のために CS 実行毎に atomic<bool> を load するオーバーヘッドあり •  CS の実行回数の合計値を X で割ったものを スループットとする •  上記実験を Y 回行い,スループットの avg, min, max を計算 11
    • Experiments •  •  •  •  •  Expr1: Expr2: Expr3: Expr4: Expr5: simple counter(s) counter(s) with delay collision timing access area size map operations 12
    • Expr1: simple counter(s) •  クリティカルセクションループ while (!isEnd_.load(std::memory_order_relaxed)) { SpinlockHle<useHLE> lk(mutex_); counter_++; } •  パラメータ –  競合率 100%: counter を全スレッドで共有 –  競合率 0%: スレッド毎に counter を持つ •  キャッシュラインが異なるように 64byte 毎に配置 Counter Thread 競合率 100% Thread 競合率 0% Counter 13
    • Expr1: result 44.7x 10 sec, 20 trials spinlock なしの 8 threads 実行で 4309M なので, isEnd.load() のオーバーヘッドは 8% 程度 14
    • Expr1: result (scaled) 競合100% のときは オーバーヘッドの分 性能悪化 10 sec, 20 trials 15
    • Expr2: counter(s) with delay •  1us delay (誤差は実測 70ns 以下) void delayUsec(uint64_t usec) { auto ts0 = std::chrono::high_resolution_clock::now(); uint64_t diff = 0; while (diff < usec * 1000) { auto ts1 = std::chrono::high_resolution_clock::now(); diff = std::chrono::duration_cast< std::chrono::nanoseconds>(ts1 - ts0).count(); } } •  クリティカルセクション while (!isEnd_.load(std::memory_order_relaxed)) { SpinlockHle<useHLE> lk(mutex_); counter_++; delayUsec(1); } 16
    • Expr2: result 10 sec, 20 trials cs が 1us でも最大 5 倍程度の性能アップを期待できる 17
    • Expr3: •  1us delay の前/後にカウンタを更新する while (!isEnd_.load(std::memory_order_relaxed)) { SpinlockHle<useHLE> lk(mutex_); if (isBefore) delayUsec(1); counter_++; if (!isBefore) delayUsec(1); } •  目的 –  競合発覚するのが CS の最初か最後かで楽観的 実行が失敗する頻度が変化するのを観察したい 18
    • Expr3: result 10 sec, 20 trials 19
    • Expr4: •  目的 –  write buffer や read flag を管理する領域は有 限なので,HLE で恩恵が受けられるアクセスサイ ズの上限を知りたい •  手段 –  X 個の 64bytes メモリ断片をスレッド毎に用意 –  CS の中で Y 個にアクセスする(重複アリ) –  他の条件を同じにするため,Y は固定 –  2 <= X <= Y で評価 –  今回は write の評価のみ 20
    • Expr4: 1-4 thread 16 clines 1 threads 3 threads 10 sec, 20 trials 2 threads 4 threads CS 内では 12 lines までのアクセスにした方が良さそう 21
    • Expr4: 5-8 thread 16 clines 5 threads 7 threads 10 sec, 20 trials 6 threads 8 threads 安定しない結果.12 lines を越えても効果があるケースも 22
    • Expr4: 5-8 thread 64 clines 5 threads 7 threads 5 sec, 100 trials 6 threads 8 threads 安定しない結果,実験方法に問題があるかも? 23
    • Expr5: •  目的: –  実用的なデータ構造で HLE の効果を知る •  手段: –  std::map<uint32_t, uint32_t> をひとつの spinlock で排他 –  read 比率を変える: 0%, 90%, 99%, 100% •  read 操作: ランダムキーで lower_bound 検索 •  write 操作: ひとつ削除,その後 insert –  初期アイテム数: 10K (約2MB), 1M (約100MB) –  (ついでに自作の btree map でも試す) 24
    • 20131022追記 •  以下 expr5 の結果グラフのスループットは全 て誤って 3 倍に集計されていたことが発覚 –  集計スクリプトのミス •  スループットを見るときは表記の 1/3 にして ご覧ください 25
    • Expr5: 10K items, read 0% std::map はスレッド数増加で HLE on が逆転 性能上昇は最大で 39% (8 threads) btree も同様の傾向 26
    • Expr5: 10K items, read 90% std::map では 2 threads 以上で HLE on が上回る. 最大46%性能Up (3 threads) btree では傾向が安定しないが 概ね同程度と言える 27
    • Expr5: 10K items, read 99% std::map は最大 2.9 倍の性能 (3 threads) btree も最大 2.4 倍の性能 (3 threads) 28
    • Expr5: 10K items, read 100% std::map は 6 threads で 7.4 倍 btree は 4 threads で 3.4 倍 29
    • Expr5: 1M items, read 0% 3 threads 以上で HLE on の方が良い std::map 6.9% up (3 threads) btree: 7.3% up (3 threads) 30
    • Expr5: 1M items, read 90% std::map は 58% up (3 threads) btree は 54% up (3 threads) 31
    • Expr5: 1M items, read 99% std::map は 2.4 倍 (3 threads) btree は 2.4 倍 (3 threads) 32
    • Expr5: 1M items read 100% std::map は 2.6 倍 (4 threads) btree は 2.6 倍 (3 threads) 33
    • Expr5: まとめ •  性能向上 –  10K items で 最大 7.4 倍 (read 100%) –  1M items で 最大 2.6 倍 (read 100%) •  現状の結論 –  データがキャッシュに乗る程度に小さく read 比 率が低いと HLE のオーバーヘッドが目立つ •  考察 –  critical section でより多くの操作をするケースも 評価すべき 34
    • HLE 評価まとめ •  手間なしで性能が向上する魔法 –  楽観的挙動 à 悲観的挙動なので 性能最悪値を保証してくれるのも魅力 –  デッドロックは従来通り気をつける必要あり •  使うべき条件 –  条件1: 競合が起きにくい (read 比率が高い) –  条件2: クリティカルセクション実行時間が短い –  条件3: アクセス対象メモリが少ない 35
    • 今後の展望 •  HLE には条件分岐予測のように elision すべきかど うかを予測して性能向上させる余地があるのではな いか? –  今回あまり調べてないので既にやってたらごめんなさい •  RTMは? –  L1 のみならず,L2/L3 そしてメモリコントローラまで TM のことを考えてくれるようになるまで様子見したい –  速度が重要じゃない用途なら STM と連動できるように なった時点で開発効率の点から有用なのではないか 36
    • おまけ: 私の単体 CPU 購入歴 •  •  •  •  •  •  AMD K6-300 Intel Pentium II 333MHz AMD Athlon 64 3200+ AMD Athlon X2 BE-2400 AMD Phenom II X4 910e AMD Phenom II X6 1065T •  こんな私が買う気になってるのだから Haswell は凄い! 37
    • 実験してみたい人へ •  用意するもの –  TSX サポート付きの Haswell CPU –  Linux OS (古いものはオススメしない) –  GCC 4.8 以降 •  ソースコード –  https://github.com/starpos/hle_bench 38
    • ありがとうございました •  ご質問,コメントはご気軽にどうぞ J 39