Performance Haskell/GHC使用“过滤器”/“列表理解”对原始排序的性能

Performance Haskell/GHC使用“过滤器”/“列表理解”对原始排序的性能,performance,sorting,haskell,functional-programming,list-comprehension,Performance,Sorting,Haskell,Functional Programming,List Comprehension,使用-O3编译,使用 quicksort [] = [] quicksort (x : xs) = quicksort (filter (< x) xs) ++ [x] ++ quicksort (filter (>= x) xs) quicksort2 [] = [] quicksort2 (x : xs) = quicksort2 [y | y <- xs, y &

使用
-O3
编译,使用

quicksort []       = []
quicksort (x : xs) = quicksort (filter (< x) xs)
                     ++ [x] ++
                     quicksort (filter (>= x) xs)
quicksort2 []       = []
quicksort2 (x : xs) = quicksort2 [y | y <- xs, y < x]
                      ++ [x] ++
                      quicksort2 [y | y <- xs, y >= x]
minisort [] = []
minisort xs = let x = minimum xs
              in  x : minisort (delete x xs)
这些不是Haskell本机合并
排序
,也不应该是

我注意到
迷你排序
始终比
快速排序
运行得快得多,考虑到所涉及操作的复杂性,这似乎是可以理解的。我不明白的是,quicksort2有一个一致的轻微边缘
quicksort2
超过了
quicksort2
。列表理解通常比过滤表达式更有效吗


到目前为止,我使用的是,与nf,
ghci
:set+s
,以及2个远程performance displayant在线编译器(,)

标准基准排序最坏情况
[50004999..1]:[Int]

benchmarking quicksort
time                 2.283 s     (2.191 s .. 2.450 s)
                     0.999 R²    (0.998 R² .. 1.000 R²)
mean                 2.434 s     (2.368 s .. 2.485 s)
std dev              79.23 ms    (0.0 s .. 88.75 ms)
variance introduced by outliers: 19% (moderately inflated)

benchmarking quicksort2
time                 2.203 s     (1.982 s .. 2.455 s)
                     0.998 R²    (0.994 R² .. 1.000 R²)
mean                 2.327 s     (2.275 s .. 2.359 s)
std dev              49.11 ms    (0.0 s .. 56.47 ms)
variance introduced by outliers: 19% (moderately inflated)

benchmarking minisort
time                 257.2 ms    (229.7 ms .. 276.4 ms)
                     0.997 R²    (NaN R² .. 1.000 R²)
mean                 274.4 ms    (264.3 ms .. 280.9 ms)
std dev              9.714 ms    (2.538 ms .. 12.94 ms)
variance introduced by outliers: 16% (moderately inflated)

quicksort2
always(不同的测试用例、顺序和上下文)的性能比
quicksort
好一点
minisort
,到目前为止,它的性能比这两者都好。

这是什么版本的GHC?您是如何测量速度的,基于什么输入?我非常惊讶,因为
filter
是使用
build/foldr
表单实现的,该表单应该类似于列表理解。如果您在GHCi中尝试一些东西,它们没有得到优化。还要注意,没有
-O3
;只需
-O2
。这种情况最终可能会改变,但从一开始就一直如此。在任何非微小列表上,
minisort
()都不会更快,因为这是O(n²)最佳情况,而任何像样的排序算法的平均情况复杂度都是O(n·logn)。你是怎么测量的?特别是,您采取了哪些措施来确保实际评估结果?我怀疑你只是列出了排序后的列表——这还不够。请发布你的基准代码和你用来运行它的过程。还要注意的是,您的“快速排序”不是随机的,因此它容易受到病理病例的影响,并且它对每个列表执行两次传递(尽管后者在这里可能并不可怕)。您正在测试的降序列表正是dfeuer所指的病理输入类型。你知道为什么吗?所以你比较了几种二次时间算法。关于为什么这里有些人比其他人慢或快,答案不会特别有趣。我读错了。这里没有列表融合的可能性。如果
quicksort
quicksort2
之间的差异是真实的(这几乎不具有统计意义,如果存在一些愚蠢的依赖于先运行哪个基准或其他什么的情况,我也不会感到惊讶),那么这可能是优化中的脆弱之处。选择排序比快速排序更简单,所以当快速排序遇到最坏的情况时,它会更快,我并不感到惊讶。