2015-12-16 79 views
4

我想在Haskell中編寫安全的超時評估函數。代碼去如下Haskell超時分歧計算

import System.Timeout 

compute, compute' :: Int -> Int 
compute i = sum [1..300000 + i] 
compute' i = last $ repeat i 

timedComp :: Int -> a -> IO (Maybe a) 
timedComp timeLeft toCompute = 
     timeout timeLeft go 
    where 
     go = toCompute `seq` return toCompute 

main = do 
    res <- timedComp 10000 (compute 0) 
    print res 

    res' <- timedComp 10000 (compute' 0) 
    print res' 

(我知道,我只評估爲WHNF。)

當我運行主,我得到的輸出只有一個沒有什麼,然後程序掛起。我試圖編譯和運行程序多線程,但它沒有幫助。在GHC 7.6.3和7.8.3上都試過。有什麼建議麼?

+3

我擔心'compute'i = last $ repeat i'是經過優化的,所以根本不需要分配。如果是這樣的話,GHC調度程序沒有機會切換到另一個Haskell線程。這是GHC的一個已知的「限制」(ok,ok,bug)。我希望有一天GHC在這種情況下至少會發出警告。 – chi

+2

爲了避免@chi提到的問題,如果它實際上是你的問題,用'-fno-omit-yield'構建 –

+0

@chi:你可以把它作爲答案嗎?也許結合裏德巴頓的建議? –

回答

3

Haskell線程的GHC實現存在限制:上下文切換僅在分配期間發生。因此,根本不執行分配的緊密循環可能會阻止調度程序運行,切換到其他線程。

這是這樣一個例子:compute' i = last $ repeat i看起來好像它的分配列表中的小區,但遺憾的是GHC能夠把它作爲優化微不足道的無限循環,清除所有分配 - GHC核心大致看起來f x = f x。這觸發了調度程序的缺點。

Reid Barton建議選擇-fno-omit-yields來解決此問題。這將導致GHC不那麼優化。