如何通过纯函数计算仅“烧CPU”来最好地“浪费”大致指定的时间?

Posted

技术标签:

【中文标题】如何通过纯函数计算仅“烧CPU”来最好地“浪费”大致指定的时间?【英文标题】:How to best "waste" a roughly specified time by only "burning CPU" with pure functional calculations? 【发布时间】:2014-03-09 12:46:28 【问题描述】:

我偶尔想在开发/测试时延迟纯算法的特定部分,所以我可以简单地通过观察惰性结果逐步建立来监控评估(这通常太快而无法在最终结果中使用) ,未延迟版本)。然后我发现自己插入了像 sum [1..1000000] `seq` q 这样丑陋的东西,这种方法很管用(虽然经常会遇到常见的 thunk-explosion 问题,因为我从来没有考虑过这个问题),但更像是反复试验。

当我想以这种方式进行一些快速测试并且懒得进行适当的分析时,是否有更好、更可控的替代方案,criterion 等?

我也想避免使用unsafePerformIO $ threadDelay,尽管我认为这实际上可能是一个合适的用途。

【问题讨论】:

是否需要循环分配? 您是否需要它在所有机器上运行给定的时间,或者如果延迟代码在性能更高的硬件上运行得更快就可以了? 从程序上讲,我更希望它只是“运行一个空循环”。时间应该大致可预测,但只能在数量级上(硬件因素很好)。 传递从getContents 获得的列表。如果您希望此列表的下一个元素可用,请按 Enter。 对于 thunk 爆炸问题,foldl' (+) 0 $ take 400000000 $ intersperse (negate 1) (repeat 1) 之类的东西似乎可以避免它们。 【参考方案1】:

这种循环解决方案避免了调用threadDelay,但仍然调用unsafePerformIO,所以也许我们并没有得到多少收获:

import Data.AdditiveGroup
import Data.Thyme.Clock
import Data.Thyme.Clock.POSIX
import System.IO.Unsafe

pureWait :: NominalDiffTime -> ()
pureWait time = let tsList = map unsafePerformIO ( repeat getPOSIXTime ) in
    case tsList of
        (t:ts) -> loop t ts
    where
        loop t (t':ts') = if (t' ^-^ t) > time
            then ()
            else loop t ts'

main :: IO ()
main = do
    putStrLn . show $ pureWait (fromSeconds 10)

更新:这是一个替代解决方案。首先确定(使用IO)实现给定延迟需要多少次迭代,然后只使用纯循环函数。

pureWait :: Integer -> Integer
pureWait i = foldl' (+) 0 $ genericTake i $ intersperse (negate 1) (repeat 1)

calibrate :: NominalDiffTime -> IO Integer
calibrate timeSpan = let iterations = iterate (*2) 2 in loop iterations
    where
    loop (i:is) = do
        t1 <- getPOSIXTime
        if pureWait i == 0
            then do
                t2 <- getPOSIXTime
                if (t2 ^-^ t1) > timeSpan
                   then return i
                   else loop is
            else error "should never happen"

main :: IO ()
main = do
    requiredIterations <- calibrate (fromSeconds 10)
    putStrLn $ "iterations required for delay: " ++ show requiredIterations
    putStrLn . show $ pureWait requiredIterations

【讨论】:

第一个解决方案,嗯... no,收益不大。但我更喜欢第二种方法。虽然还是有点罗嗦,但我想还是需要去图书馆。 ...然后还不如采取完整的 unsafe-threaddelay 路线...

以上是关于如何通过纯函数计算仅“烧CPU”来最好地“浪费”大致指定的时间?的主要内容,如果未能解决你的问题,请参考以下文章

大数据计算:如何仅用1.5KB内存为十亿对象计数

设计问题:如何最好地使用构图

如何最好地计算 TextArea 中的文本字节

如何使用 Node.js 为所有连接最好地实现 HTTPS?

如何有效地迭代 Pandas 数据帧的连续块

如何最好地接近局部阈值opengl函数