我正在尝试在Haskell中实现一个kdtree(参见implementation),但我试图聪明并在实现最近邻居算法时利用Haskells的懒惰(见第46行)。
虽然技术上是正确的,但是:
minimumBy (compare `on` qd q) vs == head . nearestNeighbours (kdtree 5 vs) $ q
==> True
基于kdtree的版本要慢得多(标准:5.38ms对138.44ms,有500k数据点)。我首先想到这是由于ordMerge
(第59行)中的模式匹配过于严格,但我重新编写了它,并且根据我的理解bs
现在应该只根据需要进行评估。
如果是这种情况,算法应该只下降到匹配的存储桶,并在检查当前最佳最近邻居是否真的是最佳候选时重新确定。
我做了一些分析,nearestNeighhbors
被调用了大约800次。鉴于树深度为8和100个测试用例,这听起来很合理,不是吗?
刚刚将我的代码上传到github:https://github.com/fhaust/threesg
这应该让你开始:
git clone https://github.com/fhaust/threesg
cd threesg
cabal sandbox init
cabal install --enable-benchmarks --enable-tests
cabal test
cabal bench --benchmark-options="+RTS -K100M -RTS"
(-K100M
是必需的,因为测试集是从500k点创建的)
在为github创建测试集时,我注意到,在正常的分布点上,kdtree搜索比线性搜索运行得快......可能我的问题不是算法...但我的测试集:(
答案 0 :(得分:0)
最后,这是一个跟踪评估顺序的问题。我在github上传了最新版本。
看看line 74:第二个列表仅在第一个列表的第一个条目与“没有更好的候选者”标准不匹配时进行评估。
Apropos标准,我做了一些benchmarking,kd-tree确实更快。
您如何看待这个解决方案?我认为代码非常简洁易读。是否存在明显的性能损失?