Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization Haskell中的严格性优化和内存分配_Optimization_Haskell_Functional Programming - Fatal编程技术网

Optimization Haskell中的严格性优化和内存分配

Optimization Haskell中的严格性优化和内存分配,optimization,haskell,functional-programming,Optimization,Haskell,Functional Programming,通过实现一个特征选择算法,我学习了一些Haskell 我在基准数据集上的性能从20秒下降到5秒,其中C程序在0.5秒内处理相同的数据集。可以找到数据集。要运行,请像这样调用编译后的二进制文件:/Mrmr 10 test\u nci9\u s3.csv 代码是,我感兴趣的是优化MutualInfo内部循环: mutualInfoInnerLoop :: Double -> Data.Vector.Unboxed.Vector (Int, Int) -> Double -> (In

通过实现一个特征选择算法,我学习了一些Haskell

我在基准数据集上的性能从20秒下降到5秒,其中C程序在0.5秒内处理相同的数据集。可以找到数据集。要运行,请像这样调用编译后的二进制文件:
/Mrmr 10 test\u nci9\u s3.csv

代码是,我感兴趣的是优化MutualInfo内部循环:

mutualInfoInnerLoop :: Double -> Data.Vector.Unboxed.Vector (Int, Int) -> Double -> (Int, Int, Double) -> Double
mutualInfoInnerLoop n xys !acc (!i, !j, !px_py)
    | n == 0 || px_py == 0 || pxy == 0 = acc
    | otherwise                        = pxy * logBase 2 ( pxy / px_py ) + acc
    where
        pxy = ( fromIntegral . U.foldl' accumEq2 0 $ xys ) / n
        accumEq2 :: Int -> (Int, Int) -> Int
        accumEq2 !acc (!i', !j')
            | i' == i && j' == j = acc + 1
            | otherwise          = acc
剖析者说:

COST CENTRE                    MODULE               %time %alloc

mutualInfoInnerLoop            Main                  75.0   47.9
mutualInfo                     Main                  14.7   32.1
parseCsv                       Main                   5.9   13.1
CAF                            GHC.Float              1.5    0.0
readInt                        Main                   1.5    1.2
doMrmr                         Main                   1.5    4.0
这表明MutualInfo InnerLoop完成了50%的分配,程序中有75%的运行时。分配令人不安

此外,该功能的核心有一个签名:

mutualInfoInnerLoop_rXG
  :: GHC.Types.Double
     -> Data.Vector.Unboxed.Base.Vector (GHC.Types.Int, GHC.Types.Int)
     -> GHC.Types.Double
     -> (GHC.Types.Int, GHC.Types.Int, GHC.Types.Double)
     -> GHC.Types.Double
[GblId,
 Arity=4,
 Caf=NoCafRefs,
 Str=DmdType U(L)LU(L)U(U(L)U(L)U(L))m]
将大多数参数显示为惰性计算和装箱(与严格和未装箱相反)

我试过刘海模式,我试过魔术师,但我似乎无法让它走得更快


有人有什么建议吗?

我目前还不是这方面的专家,但我确实看到了一个小小的改进。在你的资料中,我看到:

mutualInfo n ... = foldl' (mutualInfoInnerLoop n $ U.zip xs ys) ...
您不需要每次调用函数时都检查
n==0
,因为调用函数时从不更改
n
参数。
xys
参数也不会改变,这意味着
pxy
不会在调用之间改变,因为它完全依赖于
xys
n
。让我们利用这些东西来确保创建一个闭包,它只对这些东西进行一次评估

mutualInfoInnerLoop n xys
  | n == 0 || pxy == 0 = const
  | otherwise          = go
  where pxy = (fromIntegral . U.foldl' accumEq2 0 $ xys) / n
        accumEq2 :: Int -> (Int, Int) -> Int
        accumEq2 !acc (!i', !j')
              | i' == i && j' == j = acc + 1
              | otherwise          = acc
        go !acc (!i, !j, !px_py)
          | px_py == 0 = acc
          | otherwise  = pxy * logBase 2 ( pxy / px_py ) + acc

我不确定GHC是否足够聪明,能够独立执行此优化,也不确定这是否节省了很多时间/空间,但这是我所拥有的最好的。这些爆炸模式到处都是,我想这是不是太严格了。

我想你已经试过ghc-O2了?是的,我试过了。源代码还带有
{-#LANGUAGE BangPatterns}
{-#OPTIONS\u GHC-O2-fexcess precision-funbox strict fields}
可以提供用于基准测试的
Int
和文件吗?核心并不令人惊讶。您已将
mutualInfoInnerLoop
注释为NOINLINE,因此GHC不会将其内联。因此,所有参数都不能解除绑定。如果您将
NOINLINE
更改为
INLINE
,会发生什么?如果您的想法是要满足或击败C代码,那么我们也需要它。非常好的建议!实际上,我最终将n==0移到了domrmrmr中,这似乎是个好主意。至于这个构造,如果不解包i或j,我们就无法构造accumEq2——这让我想知道accumEq2的动态构造性质是否是问题所在。实际上,所有这些爆炸模式似乎都有帮助,只需刮去半秒钟(我们实际上在4秒左右)。哦,我忘了accumEq2中使用了i和j。我的错。