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
Performance 回忆录完成了,现在怎么办?_Performance_Haskell_Memoization - Fatal编程技术网

Performance 回忆录完成了,现在怎么办?

Performance 回忆录完成了,现在怎么办?,performance,haskell,memoization,Performance,Haskell,Memoization,我试图在Haskell中解决一个难题,并编写了以下代码: u 0 p = 0.0 u 1 p = 1.0 u n p = 1.0 + minimum [((1.0-q)*(s k p)) + (u (n-k) p) | k <-[1..n], let q = (1.0-p)**(fromIntegral k)] s 1 p = 0.0 s n p = 1.0 + minimum [((1.0-q)*(s (n-k) p)) + q*((s k p) + (u (n-k) p)) | k

我试图在Haskell中解决一个难题,并编写了以下代码:

u 0 p = 0.0
u 1 p = 1.0
u n p = 1.0 + minimum [((1.0-q)*(s k p)) + (u (n-k) p) | k <-[1..n], let q = (1.0-p)**(fromIntegral k)]

s 1 p = 0.0
s n p = 1.0 + minimum [((1.0-q)*(s (n-k) p)) + q*((s k p) + (u (n-k) p)) | k <-[1..(n-1)], let q = (1.0-(1.0-p)**(fromIntegral k))/(1.0-(1.0-p)**(fromIntegral n))]
u0p=0.0
u 1 p=1.0

u n p=1.0+最小值[((1.0-q)*(skp))+(u(n-k)p)| k我在运行编译后的版本时不会耗尽内存,但Java版本的工作方式与Haskell版本的工作方式之间存在显著差异,我将在这里说明

首先要做的是添加一些重要的类型签名。特别是,您不需要
Integer
数组索引,因此我添加了:

memoUa :: Array Int Double
memoSa :: Array Int Double
我使用
ghc mod check
找到了这些。我还添加了一个
main
,以便您可以从命令行运行它:

import System.Environment

main = do
  (arg:_) <- getArgs
  let n = read arg
  print $ mua n
然后当我们像这样调用程序时:

memo 1000 +RTS -s
我们将获得如下分析输出:

164.31333233347755
      98,286,872 bytes allocated in the heap
      29,455,360 bytes copied during GC
         657,080 bytes maximum residency (29 sample(s))
          38,260 bytes maximum slop
               3 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0       161 colls,     0 par    0.03s    0.03s     0.0002s    0.0011s
  Gen  1        29 colls,     0 par    0.03s    0.03s     0.0011s    0.0017s

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    0.21s  (  0.21s elapsed)
  GC      time    0.06s  (  0.06s elapsed)
  RP      time    0.00s  (  0.00s elapsed)
  PROF    time    0.00s  (  0.00s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time    0.27s  (  0.27s elapsed)

  %GC     time      21.8%  (22.3% elapsed)

  Alloc rate    468,514,624 bytes per MUT second

  Productivity  78.2% of total user, 77.3% of total elapsed
需要注意的重要事项包括:

  • 最高居住期
  • 总时间
  • %GC时间(或生产率)
最大驻留时间是衡量程序需要多少内存的指标。%GC时间花费在垃圾收集和生产效率上的时间比例是补充(100%-%GC时间)

如果您针对各种输入值运行程序,您将看到大约80%的生产率:

   n       Max Res.  Prod.   Time   Output
   2000     779,076  79.4%   1.10s  328.54535361588535
   4000   1,023,016  80.7%   4.41s  657.0894961398351
   6000   1,299,880  81.3%   9.91s  985.6071032981068
   8000   1,539,352  81.5%  17.64s  1314.0968411684714
  10000   1,815,600  81.7%  27.57s  1642.5891214360522
这意味着大约20%的运行时间用于垃圾收集。此外,随着
n
的增加,内存使用率也在增加

事实证明,通过告诉Haskell计算数组元素的顺序,而不是依赖惰性计算,我们可以显著提高生产率和内存使用率:

import Control.Monad (forM_)

main = do
  (arg:_) <- getArgs
  let n = read arg
  forM_ [1..n] $ \i -> mua i `seq` return ()
  print $ mua n

这里有一些有趣的观察结果:生产率提高,内存使用率下降(在输入范围内保持不变)但是运行时间到了。这表明我们强制执行的计算比我们需要的要多。在像Java这样的命令式语言中,你必须给出一个求值顺序,这样你才能确切地知道需要执行哪些计算。看看你的Java代码,看看它正在执行哪些计算,这会很有趣。

我不会耗尽内存n我运行编译后的版本,但是Java版本的工作方式与Haskell版本的工作方式有很大区别,我将在这里说明

首先要做的是添加一些重要的类型签名。特别是,您不需要
Integer
数组索引,因此我添加了:

memoUa :: Array Int Double
memoSa :: Array Int Double
我使用
ghc mod check
找到了这些。我还添加了一个
main
,以便您可以从命令行运行它:

import System.Environment

main = do
  (arg:_) <- getArgs
  let n = read arg
  print $ mua n
然后当我们像这样调用程序时:

memo 1000 +RTS -s
我们将获得如下分析输出:

164.31333233347755
      98,286,872 bytes allocated in the heap
      29,455,360 bytes copied during GC
         657,080 bytes maximum residency (29 sample(s))
          38,260 bytes maximum slop
               3 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0       161 colls,     0 par    0.03s    0.03s     0.0002s    0.0011s
  Gen  1        29 colls,     0 par    0.03s    0.03s     0.0011s    0.0017s

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    0.21s  (  0.21s elapsed)
  GC      time    0.06s  (  0.06s elapsed)
  RP      time    0.00s  (  0.00s elapsed)
  PROF    time    0.00s  (  0.00s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time    0.27s  (  0.27s elapsed)

  %GC     time      21.8%  (22.3% elapsed)

  Alloc rate    468,514,624 bytes per MUT second

  Productivity  78.2% of total user, 77.3% of total elapsed
需要注意的重要事项包括:

  • 最高居住期
  • 总时间
  • %GC时间(或生产率)
最大驻留时间是衡量程序需要多少内存的指标。%GC时间花费在垃圾收集和生产效率上的时间比例是补充(100%-%GC时间)

如果您针对各种输入值运行程序,您将看到大约80%的生产率:

   n       Max Res.  Prod.   Time   Output
   2000     779,076  79.4%   1.10s  328.54535361588535
   4000   1,023,016  80.7%   4.41s  657.0894961398351
   6000   1,299,880  81.3%   9.91s  985.6071032981068
   8000   1,539,352  81.5%  17.64s  1314.0968411684714
  10000   1,815,600  81.7%  27.57s  1642.5891214360522
这意味着大约20%的运行时间用于垃圾收集。此外,随着
n
的增加,内存使用率也在增加

事实证明,通过告诉Haskell计算数组元素的顺序,而不是依赖惰性计算,我们可以显著提高生产率和内存使用率:

import Control.Monad (forM_)

main = do
  (arg:_) <- getArgs
  let n = read arg
  forM_ [1..n] $ \i -> mua i `seq` return ()
  print $ mua n

这里有一些有趣的观察结果:生产率提高,内存使用率下降(在输入范围内保持不变)但是运行时间到了。这表明我们强制执行的计算比我们需要的要多。在像Java这样的命令式语言中,您必须给出一个求值顺序,这样您就可以确切地知道需要执行哪些计算。查看Java代码以了解它正在执行哪些计算是很有趣的。

示例输入和预期输出会有帮助的。还有输入签名!您是否尝试过使用
-O
编译,或者是在GHCi中运行此功能?您是否可以将其分解为几个较小的表达式,例如在
where
子句中,或者至少将其拆分为多行?这190个字符行很难读取。通过这种方式,可读性要高得多但是它仍然需要类型签名示例输入和预期输出会有所帮助。类型签名!您是否尝试过使用
-O
编译,或者您正在GHCi中运行此功能?您是否可以将其分解为一些较小的表达式,例如在
where
子句中,或者至少将其拆分为多行?这些190个字符行很难阅读。这样可读性好得多,但仍然需要类型签名。我添加了java版本。顺便说一句,我不认为可以进行比需要更多的计算。我希望由于“最小”的原因,需要所有东西。我不知道你在哪里设置
s[k]
常规
k
(即不是1或
n
)(数组
u[]
)的所有其他
s[]
值是否都等于0?我已经添加了java版本。顺便说一句,我看不出有多少计算可以做得比需要的多。我希望由于“最小值”的原因,一切都需要。我看不到你在哪里设置
s[k]
对于常规
k
(即不是1或
n
)(对于数组
u[]
)也是如此,
s[]
的所有其他值是否都等于0?