Sorting 减少分配排序大列表(或向量)

Sorting 减少分配排序大列表(或向量),sorting,haskell,allocation,Sorting,Haskell,Allocation,我试图在我的程序中减少GC时间。主要嫌疑犯是以下代码: Data.Vector.Unboxed.fromList . take n . List.sortBy (flip $ Ord.comparing id) $ [ ( sum [ (c + a) * wsum z | (z,c) <- IntMap.toList zt_d ] , d) | d <- IntMap.keys $ m , let zt_d = IntMap.findWithDefault IntMa

我试图在我的程序中减少GC时间。主要嫌疑犯是以下代码:

Data.Vector.Unboxed.fromList . take n . List.sortBy (flip $ Ord.comparing id) 
 $ [ ( sum [ (c + a) * wsum z | (z,c) <- IntMap.toList zt_d ] , d)
   | d <- IntMap.keys $ m
   , let zt_d = IntMap.findWithDefault IntMap.empty d $ m ]

排序看起来确实会导致大量的分配。虽然排序是在列表上执行的,但这不能完全改变,因为排序列表会导致许多中间列表的构建。如有必要,您可以尝试在
MVector
上进行排序,例如使用提供高效排序算法的包

然而,还有进一步的低效率,这导致了更多的资源分配超出了必要的范围

Data.Vector.Unboxed.fromList . take n . List.sortBy (flip $ Ord.comparing id) 
 $ [ ( sum [ (c + a) * wsum z | (z,c) <- IntMap.toList zt_d ] , d)
   | d <- IntMap.keys $ m
   , let zt_d = IntMap.findWithDefault IntMap.empty d $ m ]
Data.Vector.unbox.fromList。以n为例。List.sortBy(翻转$Ord.id)

$[(总和[(c+a)*wsum z |(z,c)为什么
flip$Ord.comparing id
而不是
flip compare
?为什么不先将其放入向量中,然后使用
vector algorithms
包对向量进行排序?@ThomasM.DuBuisson:vector algorithms排序函数只对可变向量起作用,不是吗?是的,它们需要可变向量。因此,可以用l填充可变向量ist,对其排序,然后冻结以获得一个不可变向量。不像fromList中的
那么优雅。以n.sortBy foo
为例,但如果它更有效,这是一个很好的折衷。上述排序代码可以在几秒钟内根据一个稍微复杂的比较函数对约300万
Int
的列表进行排序(令人惊讶的是,堆和介绍排序要比合并慢得多)。如果你的列表只包含几千个元素,我想你会有更深层次的问题。我们能看到更多的代码吗?谢谢你的建议。有趣的是,我没有看到IntMap中愚蠢的查找:(.修复它会有一个小的加速。如果在MVector上使用inplace排序有帮助,我会试试。
Data.Vector.Unboxed.fromList . take n . List.sortBy (flip $ Ord.comparing id) 
 $ [ ( sum [ (c + a) * wsum z | (z,c) <- IntMap.toList zt_d ] , d)
   | d <- IntMap.keys $ m
   , let zt_d = IntMap.findWithDefault IntMap.empty d $ m ]
d <- IntMap.keys m, let zt_d = IntMap.findWithDefault IntMap.empty d m
-- The '$' are unnecessary, I left them out
(d,zt_d) <- IntMap.assocs m