Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
速いクイックソート: Pattern-defeating quicksort
Search
WATANABE Yuki
August 24, 2022
Programming
0
410
速いクイックソート: Pattern-defeating quicksort
社内勉強会から。Pattern-defeating quicksort アルゴリズムの大まかな説明。
WATANABE Yuki
August 24, 2022
Tweet
Share
More Decks by WATANABE Yuki
See All by WATANABE Yuki
C++ はなぜあんなにも複雑なのか
magicant
0
87
鉄道シミュレーターで自動運転を実装した話
magicant
0
320
ドキュメント、書けてますか?
magicant
0
120
Other Decks in Programming
See All in Programming
KIKI_MBSD Cybersecurity Challenges 2025
ikema
0
1.3k
高速開発のためのコード整理術
sutetotanuki
1
400
並行開発のためのコードレビュー
miyukiw
0
290
疑似コードによるプロンプト記述、どのくらい正確に実行される?
kokuyouwind
0
390
Apache Iceberg V3 and migration to V3
tomtanaka
0
160
Amazon Bedrockを活用したRAGの品質管理パイプライン構築
tosuri13
5
760
15年続くIoTサービスのSREエンジニアが挑む分散トレーシング導入
melonps
2
220
Basic Architectures
denyspoltorak
0
680
今こそ知るべき耐量子計算機暗号(PQC)入門 / PQC: What You Need to Know Now
mackey0225
3
380
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
Fluid Templating in TYPO3 14
s2b
0
130
IFSによる形状設計/デモシーンの魅力 @ 慶應大学SFC
gam0022
1
310
Featured
See All Featured
Facilitating Awesome Meetings
lara
57
6.8k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
270
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
380
RailsConf 2023
tenderlove
30
1.3k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
750
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
120
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
410
Navigating Team Friction
lara
192
16k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.6k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
170
Transcript
速いクイックソート 渡邊裕貴 / 2022-08-24
Pattern-defeating quicksort • Orson Peters という人が 2015 年ごろに発明した不安定ソートアルゴリズム • クイックソートを速くするいろいろな工夫の集大成みたいな感じ
• オリジナルのコードは C++ で書かれている • Rust の標準ライブラリーで採用された • 最近 Go の標準ライブラリーでも採用された
1分でわかる普通のクイックソート 5 4 1 6 7 3 2 9 8
配列の中から一つ軸を選ぶ (pivot) 2 4 1 3 5 7 6 9 8 軸未満→軸→軸以上 の順になるように入れ替える 以下、前後それぞれ繰り返し 2 4 1 3 5 7 6 9 8 1 2 4 3 5 6 7 9 8
クイックソートの計算量 全ての分割が二等分になる場合が最も効率的で、O(n log n) 4 3 7 6 1 5
2 2 3 1 4 6 5 7 1 2 3 4 5 6 7 n log n
クイックソートは遅い時もある (1) 常に配列の先頭を軸にする場合、配列が元からソート済みだと分割が偏る 1 2 3 4 5 6 7
n 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 n O(n2)
軸の選び方の工夫 • 配列の先頭 • 配列の真ん中 • 三つ選んで中央値を取る ◦ 3 回の比較でできる
• John Tukey’s ninther ◦ 「三つ選んで中央値を取る」を 3 回やって中央値を取る ◦ 12 回の比較でできる 簡単 分割が偏りにくい
クイックソートは遅い時もある (2) 同じ値がたくさんある場合、分割が偏る 1 1 1 1 1 1 1
n 1 1 1 1 1 1 1 1 1 1 1 1 1 1 n 1 1 1 1 1 1 1 どれを選んでも軸は 1 O(n2)
軸に等しい値の振り分けを工夫する 1 1 2 1 1 1 1 1 1
2 1 1 1 1 新しい軸が前回の軸と等しいなら 同じ値がたくさんある公算が高い 軸に等しい値→軸より大きい値 の順に入れ替える 軸に等しい値どうしはもうソートしなくていい O(n2) が O(n) になった 1 1 1 1 1 1 2
クイックソートは遅い時もある (3) それでも分割が偏る可能性はゼロではない • とても運が悪かった場合 • 分割が偏るように仕組まれている場合
軸の候補をシャッフルする 分割が偏っていた場合 (分割比が 1:7 未満の場合) は 次の軸の選び方 (John Tukey’s ninther
で使う値) を変える • オリジナル版: ◦ 配列の端っこや真ん中だけじゃなくて四等分した位置から選ぶ • Rust/Go 版: ◦ 四等分した位置だけじゃなくてランダムに選ぶ ▪ 簡易的な乱数を使う
最後の手段: ヒープソート 偏った分割が log n 回発生したら、諦めてヒープソートに移行する ヒープソートとは: • 二分木と等価な構造を配列上に再現するソート手法 •
クイックソートより 2 倍くらい遅い • 最悪計算量 O(n log n) が保証されている
部分挿入ソートによる高速化 • 以下の条件が全て満たされたとき、配列全体がソート済みの可能性が高そう ◦ 前回の分割比が 1:7 より悪くなかった ◦ 前回の分割時、軸の前後で入れ替わった要素がなかった ◦
John Tukey’s ninther で軸を選ぶとき候補となる九つの値がソート済みだった • この場合は挿入ソートを試す ◦ ただし一定ループ回数で終わらなければ諦める (O(n))
配列の分割 (軸前後の値の入れ替え) の遅さ 典型的コード while (left < right && array[left]
< pivot) left++; while (left < right && array[right] >= pivot) right--; if (left < right) { tmp = array[left]; array[left] = array[right]; array[right] = tmp; } 分岐予測の外れやすい分岐 1 回の入れ替えで 3 回の代入
BlockQuicksort による高速化 1. 配列の先頭 128 個と末尾 128 個を一気に軸と比較して 入れ替えるべき値の位置を一時配列にまとめる ◦
ループ回数を固定したことで分岐予測が当たるようになる ◦ ループアンローリングも可能に 2. 一次配列に入った位置の値を一気に入れ替える ◦ 2n 個の値を 2n+1 回の代入で入れ替える tmp
まとめ Pattern-defeating quicksort にはソートを速くするいろんな工夫が詰まっている • 中央値に近い値を軸にする: John Tukey’s ninther •
軸に等しい値を効率よく集める • 軸の候補をシャッフルする • 再帰回数が O(log n) を超えそうならヒープソート • 既にソート済みっぽいなら挿入ソート • 値の入れ替えを速くする: BlockQuicksort