我尝试编码以计算函数成本的时间
list <- buildlist 10000 10000
starttime <- getClockTime
let sortedlist = quicksort list
endtime <- getClockTime
let difftime = diffClockTimes endtime starttime
功能构建列表:
buildlist :: Int -> Int -> IO [Int]
buildlist n m = do
seed <- getStdGen
let l = randomRs (0, m) seed
let list = take n l
return list
功能快速排序:
quicksort [] = []
quicksort (x:xs) =
let head = [a|a<-xs,a<=x]
tail = [a|a<-xs,a>x]
in quicksort head ++ [x] ++ quicksort tail
第一个问题:当我输出difftime时,无论列表有多长,它总是为零。
第二个:我想知道Real World Haskell代码中的“&gt;&gt; =”是什么意思。
getClockTime >>= (\(TOD sec _) -> return sec)
第三:我这是为了从 TimeDiff 变量中获取 tdSec 和 tdPicosec 。 有没有更简单的方法?
time <-(\(TimeDiff _ _ _ _ _ s ps) -> return [ ( \a -> fromIntegral a :: Double ) s , ( \a -> fromIntegral a :: Double ) ps ] ) difftime
答案 0 :(得分:11)
您的代码不会对列表进行排序!它只是将名称sortedlist
定义为quicksort list
,但在实际需要该值之前不会计算。那是懒惰的评价。我们不会用这种语言做额外的工作。
由于基准是额外无用的工作(这就是重点),这使基准测试变得困难。
您的选择
seq
。 seq
具有类型a -> b -> b
,并且具有评估其第一个参数的行为,即所谓的“弱头正常形式”。在这里,由于您要强制使用整个列表,因此您可能需要使用deepseq
>>=
是monadic绑定运算符。此处需要IO
类型的IO a
操作和函数a -> IO b
,并将它们组合在一起以生成类型为IO b
的新操作。这与表示法的作用相同。 foo >>= \x -> expr
与
do x <- foo
expr
事实上,do
符号只是>>=
我不确定问题3中的问题是什么 - 也许它应该得到自己的Stackoverflow问题。
答案 1 :(得分:4)
difftime
始终为零,因为Haskell的惰性评估顺序已经完全优化了实际排序。程序中的任何内容都不会访问sortedlist
,因此它甚至都不会被计算出来。
如另一个答案中所述,您可以强制您的程序使用来自sortedlist
的名为deepseq
的神奇函数来计算Control.Deepseq
。 deepseq v
相当于id
,但它具有强制v
被完全评估的副作用。
starttime <- getClockTime
let sortedlist = quicksort list
endtime <- deepseq sortedlist getClockTime
至于你的第二个问题,是的,有一种更简单的方式来访问TimeDiff
的字段。 Data
声明中的字段名称为getter函数。因此,tdSec td
获得td
秒,tdPicosec td
获得皮秒。
答案 2 :(得分:3)
为了衡量纯函数的评估时间,您可能会对我的Chronograph
包感兴趣:http://hackage.haskell.org/package/chronograph
以下是如何使用它的简短示例:
Prelude Data.Chronograph> :m Data.Chronograph Data.List
Prelude Data.Chronograph Data.List> let theList = reverse [1..1000]
Prelude Data.Chronograph Data.List> sum theList
500500
Prelude Data.Chronograph Data.List> let timed = chronoNF (sort theList)
Prelude Data.Chronograph Data.List> measure timed
0.000062s
Prelude Data.Chronograph Data.List> head $ val timed
1
几点:
theList
的总和,以强制其构造和逆转。如果它不是强制在这里,那么构建成本将归因于对chronoNF
chronoNF
使用与deepseq
相同的策略进行评估,正如其他一些答案所讨论的那样。计时码表为不同的评估策略提供其他功能。例如,我们可以评估弱头正常形式,这实际上不会对列表进行完全排序。计时码表还可以测量IO
个表达式,但这些表达式通常比非IO表达式更容易处理。