如何在Haskell中实现快速、懒惰的KDTree?

如何在Haskell中实现快速、懒惰的KDTree?,haskell,lazy-evaluation,nearest-neighbor,kdtree,Haskell,Lazy Evaluation,Nearest Neighbor,Kdtree,我试图在Haskell中实现kdtree(请参见),但在实现最近邻算法(请参见第46行)时,我试图变得聪明并利用Haskell的懒散性 虽然这在技术上是正确的,但是: minimumBy (compare `on` qd q) vs == head . nearestNeighbours (kdtree 5 vs) $ q ==> True 基于kdtree的版本要慢得多(标准:5.38ms vs 138.44ms,500k数据点)。我最初认为这是由于ordMerge(第59行)中的模式

我试图在Haskell中实现kdtree(请参见),但在实现最近邻算法(请参见第46行)时,我试图变得聪明并利用Haskell的懒散性

虽然这在技术上是正确的,但是:

minimumBy (compare `on` qd q) vs == head . nearestNeighbours (kdtree 5 vs) $ q
==> True
基于kdtree的版本要慢得多(标准:5.38ms vs 138.44ms,500k数据点)。我最初认为这是由于
ordMerge
(第59行)中的模式匹配过于严格,但我重新编写了它,根据我的理解,
bs
现在只应根据需要进行评估

如果是这种情况,算法应该只下降到匹配的桶,并重新搜索,同时检查当前最佳最近邻是否真的是最佳候选

我做了一些分析,最近的邻居被调用了大约800次。考虑到树的深度为8和100个测试用例,这听起来是合理的,不是吗


刚刚将我的代码上载到github:

这应该让你开始:

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搜索比线性搜索运行得快得多。。。可能我的问题不是算法。。。但是我的测试集:(

最后,这是一个跟踪评估顺序的问题。我将最新版本上传到了

看一看:只有当第一个列表的第一个条目与“不可能有更好的候选者”标准不匹配时,才会对第二个列表进行评估

就标准而言,我做了一些,kd树确实更快


你觉得这个解决方案怎么样?我认为代码非常简洁易读。有没有明显的性能损失?

你试过分析这个函数吗?是的……但这对我没有帮助。它大部分时间都花在
nearestneights.nnl
nearestneights.nnr
上。你在比较kd树,然后用蛮力找到最近的邻居?@DiegoNolan…不,在做基准测试之前,kdtree是强制的。我希望我写的是正确的。你有
main
函数和我们可以使用的示例数据吗?我注意到的主要问题是
ordMerge
可能没有内联,:try应用蹩脚的静态参数转换技巧,或者尝试
或merge f q p n d=go where go=…
(更好的无点风格)因此递归在常量args上是封闭的。希望结合
dist'
的内联将
f
的应用程序共享给
p
q
编译器。让我们知道您的发现