如何在使用GHC编译的Haskell函数中找到分配



我使用GHC 7.4编译以下函数:

nodups' :: [Int] -> Bool
nodups' = ok empty
where ok _ [] = True
ok seen (n:ns) = not (n `member` seen) && ok (n `insert` seen) ns
member n word = testBit word n
insert n word = setBit word n
empty = 0 :: Int

该函数在一个小整数列表中查找重复的元素。集合CCD_ 1是作为比特向量的一组小整数的表示。探查器(与ghc -prof -auto-all一起运行)声称ok函数占总分配的22%。看看-ddump-simpl的输出,我不明白为什么要分配这个代码。我检查了一下,据我所知,是而不是insert的调用分配了一个thunk。

我应该看什么来识别代码中正在分配的部分?

一般

我知道函数式语言的简单(科学)实现,如果我没记错的话,有一个G-Machine可以与Haskell一起使用。

这意味着(如果我没有记错的话)你的程序状态被表示成一个"树",其中的节点是(为了简单起见)你在代码中使用的函数。叶子将是它的论据。"G-Maschine"然后沿着"Spine"(节点的左侧链)查找,并在一组可用的"Function"("Supercompinators"?)中查找它可以应用的模式匹配。如果从定义的左侧识别出mattern匹配,则该匹配将被定义的右侧替换。

这意味着即使是像这样的简单线路

ok seen (n:ns) = not (n `member` seen) && ok (n `insert` seen) ns

甚至

(n:ns) = ns

正在计算机内存中执行某些操作,即匹配模式

...
...
(:)
/   
n     ns

并将其替换为

...
...
ns

最终结果可能比输入消耗更少的内存,但这是一个动态步骤,因此必须在某个地方进行。如果这种情况一次又一次地重复(在"紧密循环"中),那么这将使您的CPU繁忙,也会使您的内存繁忙——仅仅因为G-Machine正在运行。(正如我所说,我不确定G-Machine-概念是否适用于此,但我想它是类似的)。

具体猜测

member n word = testBit word n
insert n word = setBit word n

除此之外,我还有一些怀疑。CCD_ 6和CCD_。如果是这样的话,可能需要一些工作。如果它们是适当的数组,那也没关系。如果它们是一种映射或集合。。。好可能会涉及到代价高昂的哈希?或者通过使用大量(昂贵的?)比较操作的平衡树来实现?

最新更新