Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
俺の kd-tree
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Terada Yuichiro
November 24, 2020
Programming
1.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
俺の kd-tree
Rust で kd-tree を自作し、crates.io に公開しました。kd tree とは?パフォーマンスは? 設計は? といったあたりをまとめた発表資料です。
Terada Yuichiro
November 24, 2020
More Decks by Terada Yuichiro
See All by Terada Yuichiro
WebGPU 触ってみた
u1roh
0
2k
【STUDDi】WebGL で学ぶ 3D Graphics の概略
u1roh
0
1.4k
Graph in Rust with unsafe
u1roh
2
1.5k
Other Decks in Programming
See All in Programming
React Native経験者が Flutterを30⽇間触って驚いたこと
3saito
0
160
AmebaブログはKMPから卒業します
kmars0605
0
320
はじめてのPLATEAU
nokonoko1203
1
560
TanStack Vue Query と Pinia Colada から学ぶ非同期状態の型設計
aoshi
0
620
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
250
私なりのハーネスエンジニアリング ~独自の言語処理系の開発を通して~
seosoft
0
180
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
410
Materialが消えた日 〜真っ白なFlutterキャンバスにRenderObjectで絵を描く〜
umigishiaoi
0
150
コーディング自動化の次へ。人の介入をゼロにするファクトリーとサポートAIによる実践
timakin
5
5.1k
JIS keyboard support in Omarchy
lef237
0
180
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
14
11k
느린 네트워크와 저사양 디바이스 사용자를 위한 웹뷰 로딩 시간 개선기
kmkim
1
200
Featured
See All Featured
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
1.1k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.2k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
Un-Boring Meetings
codingconduct
0
490
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
760
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
540
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
570
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
630
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
550
Marketing to machines
jonoalderson
1
6k
Transcript
俺の kd-tree 2020-11-24 Y.Terada @ CADDi
自己紹介 • てらだ( @u_1roh ) • CADDi で図面の画像解析 に取り組んでいます。 •
Rust でアルゴリズム、い いですよね!
こんなことを話します • kd-tree を自作して crates.io に publish してみた • そもそも
kd-tree とは? • なぜ自作したの? • どんな実装? • パフォーマンスは?
kd-tree とは • k-dimensional tree • k 次元空間の点群を高速に探索可能にするデータ構造 • こんな探索が出来ます
– 【最近傍探索】点群から、指定座標に最も近い点を探索 – 【 k 近傍探索】近いものから k 個探索( k が被ってる…) – 【領域探索】指定領域に含まれる点を全て探索
kd-tree の構築( 2D の場合) • 2 分木のノードに点をひとつ格納 • X で分割
→ Y で分割 → X で分割 → Y で分割 → … https://www.datasciencecentral.com/profiles/blogs/implementing-kd-tree-for-fast-range-search-nearest-neighbor
最近傍探索 問合せ点 Q この枝における 最近傍点 探索不要な枝 探索済みの枝
crates.io を探すと
使ってみた • `kdtree` – 遅い – 点の逐次追加でツリーを構築するスタイル – 任意次元の kd
tree が作れる – 点座標の数値型は `num_traits::Float` 型(つまり `f64` と `f32`) – 型が `KdTree<f64, T, [f64; 3]>` みたいになる(`f64` を 2回書く) • `fux_kdtree` – 速い( `kdtree` の 2.5〜 3倍) – 点の配列から一気に構築するスタイル – 3次元までしか作れない – 点座標の数値型は `f64` のみ – `fux_kdtree::kdtree::KdtreePointTrait` を実装しないといけない
作りたいもの • `fux_kdtree` 並の速度で、 • 任意次元で使えて、 • 整数値の座標値が扱えて、 • 設計が洗練されているもの
できた!
ベンチマーク(構築処理) fux_kdtree kdtree 俺の (f64) 俺の (i32) [0, 1]^3 の空間に
一様な乱数で 10^n 個の点を生成 10^2 点 10^3 点 10^4 点
ベンチマーク(最近傍探索) fux_kdtree kdtree 俺の (f64) 俺の (i32) 10^2 点 10^4
点 10^3 点
機能はまだ足りない • 最近傍探索しかできない – ◦ 【最近傍探索】指定座標に最も近い点を探索 – ☓ 【 k
近傍探索】近いものから k 個探索 – ☓ 【領域探索】指定領域に含まれる点を全て探索 • 今後、機能追加していきたい
俺の kd-tree 使い方 編
基本のき use kd_tree::KdTree; let items: Vec<[i32; 3]> = vec![[1, 2,
3], [3, 1, 2], [2, 3, 1]]; let kdtree: KdTree<[i32; 3]> = KdTree::build(items); assert_eq!(kdtree.nearest(&[3, 1, 2]).unwrap().item, &[3, 1, 2]); • KdTree<[i32; 3]> ← 型がシンプル! • 整数座標が使える!(※ unsigned はダメ)
f64 の座標を使う • 浮動小数点座標の場合は build_by_ordered_float() を使う。 – f64 は Ord
を実装していないので。 – ordered_float::OrderedFloat を利用 use kd_tree::KdTree; let kdtree: KdTree<[f64; 3]> = KdTree::build_by_ordered_float(vec![ [1.0, 2.0, 3.0], [3.0, 1.0, 2.0], [2.0, 3.0, 1.0] ]); assert_eq!( kdtree.nearest(&[3.1, 0.9, 2.1]).unwrap().item, &[3.0, 1.0, 2.0] );
マップのようにも使えます • KdMap<P,T> … Map のように使える kd tree – P
に点座標 – T には任意の型が入る use kd_tree::KdMap; let kdmap: KdMap<[isize; 3], &'static str> = KdMap::build(vec![ ([1, 2, 3], "foo"), ([2, 3, 1], "bar"), ([3, 1, 2], "buzz"), ]); assert_eq!(kdmap.nearest(&[3, 1, 2]).unwrap().item.1, "buzz");
KdPoint カスタム実装 use kd_tree::{KdPoint, KdTree}; struct Item { point: [f64;
2], id: usize } impl KdPoint for Item { type Scalar = f64; type Dim = typenum::U2; // 2 dimensional tree. fn at(&self, k: usize) -> f64 { self.point[k] } } let kdtree: KdTree<Item> = KdTree::build_by_ordered_float(vec![ Item { point: [1.0, 2.0], id: 111 }, Item { point: [2.0, 3.0], id: 222 }, Item { point: [3.0, 4.0], id: 333 }, ]); assert_eq!(kdtree.nearest(&[1.9, 3.1]).unwrap().item.id, 222);
KdSlice • KdTree のスライス型( String に対する str ) – Sized
ではない → 常に参照型で扱う – KdTree は Deref<Target=KdSlice<...>> を実装 • KdSlice::sort() は items を move しない(ソートするだ け) use kd_tree::KdSlice; let mut items: Vec<[i32; 3]> = vec![[1, 2, 3], [3, 1, 2], [2, 3, 1]]; let kdtree: &KdSlice<[i32; 3]> = KdSlice::sort(&mut items); assert_eq!(kdtree.nearest(&[3, 1, 2]).unwrap().item, &[3, 1, 2]);
俺の kd-tree データ構造 編
バランス良く構築 8 個 8 個 4 個 3 個 4
個 3 個
構築フロー items: &mut [T] x 座標でソート ↑items.len()/2 y 座標でソート ↑items.len()/2
x 座標でソート ↑items.len()/2 このまま実装すると ソートが多いので遅い
Quick select • 必要なのはソートではない – 中央値の左右で要素が分かれていれば良い – 左右それぞれの枝はソートされている必要がない • Quick
select • `pdqselect` クレート • k 番目を境に要素を分ける
`kd_sort_by()`
並び替えるだけで kd tree になる • binary-tree と似ている – [T] を
sort() しておけば binary_search() できる – 同様に、 [T] を並び替えておけば最近傍探索できる • 構築に必要なのは次元と kd_compare だけ – (注:最近傍探索は kd_compare だけでは足りません。距離が測 れないといけないので。) • このシンプルさ&柔軟さを最大限に活かした設計にしたい。
KdSliceN<T, N> pub struct KdSliceN<T, N: Unsigned>(PhantomData<N>, [T]); impl<T, N:
Unsigned> KdSliceN<T, N> { pub fn sort_by<F>(items: &mut [T], compare: F) -> &Self where F: Fn(&T, &T, usize) -> Ordering + Copy, { kd_sort_by(items, N::to_usize(), compare); unsafe { &*(items as *const _ as *const Self) } } } 次元 unsized 参照を返す unsafe を使ってキャスト
KdTreeN<T, N> pub struct KdTreeN<T, N: Unsigned>(PhantomData<N>, Vec<T>); impl<T, N:
Unsigned> KdTreeN<T, N> { pub fn build_by<F>(mut items: Vec<T>, compare: F) -> Self where F: Fn(&T, &T, usize) -> Ordering + Copy, { kd_sort_by(&mut items, N::to_usize(), compare); Self(PhantomData, items) } }
KdPoint
KdPoint の実装
Type aliases pub type KdSlice<T> = KdSliceN<T, <T as KdPoint>::Dim>;
pub type KdTree<T> = KdTreeN<T, <T as KdPoint>::Dim>; pub type KdMap<P, T> = KdTree<(P, T)>; pub type KdMapSlice<P, T> = KdSlice<(P, T)>;
まとめ • 自作 kd-tree を crates.io に公開した • 性能 –
`kdtree` より速い(構築も探索も) – 探索は `fux_kdtree` より速い • 機能 – 整数座標が扱える – 高次元が扱える ※ CADDi では Rust でアルゴリズムを書きたいエンジニアを募集しています
None