Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Timeout diverging computation

I'm trying to write a safe timing-out evaluation function in Haskell. The code goes as follows

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'

(I know that I only evaluate to WHNF.)

When I run main, I get only one Nothing on output and then the program hangs. I tried to compile and run the program multi-threaded but it doesn't help. Tried on both GHC 7.6.3 and 7.8.3. Any suggestions?

like image 571
Tomáš Jakl Avatar asked Dec 16 '15 16:12

Tomáš Jakl


1 Answers

There's a limitation in the GHC implementation of Haskell threads: context switches occur only during allocation. As a consequence, tight loops which perform no allocation at all can prevent the scheduler to run, switching to other threads.

This is one of such examples: compute' i = last $ repeat i looks as if it's allocating list cells, but unfortunately GHC is able to optimize it as a trivial infinite loop, removing all allocation -- GHC Core looks roughly as f x = f x. This triggers the scheduler shortcoming.

Reid Barton suggests the option -fno-omit-yields to work around this. This will cause GHC not to optimize so much.

like image 83
chi Avatar answered Oct 29 '22 04:10

chi