2015-12-16 1 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. Это известное «ограничение» (ok, ok, ошибка) GHC. Надеюсь, что однажды GHC, по крайней мере, выпустит предупреждение в таких случаях. – chi

+2

Чтобы избежать проблемы, упомянутой @chi, если она на самом деле ваша проблема, постройте с помощью '-fno-omit-yields' –

+0

@chi: Не могли бы вы сказать, что это ответ? Может быть, в сочетании с предложением Рейда Бартона? –

ответ

3

Существует ограничение в реализации потоков Haskell в GHC: коммутаторы контекста встречаются только при распределении. Как следствие, тесные циклы, которые вообще не выполняют выделение, могут препятствовать запуску планировщика, переключаясь на другие потоки.

Это один из таких примеров: compute' i = last $ repeat i выглядит, как будто это выделение список клеток, но, к сожалению, GHC может оптимизировать его как тривиальный бесконечный цикл, удаляя все выделения - GHC Ядро выглядит примерно как f x = f x. Это вызывает недостаток планировщика.

Reid Barton предлагает вариант -fno-omit-yields, чтобы обойти это. Это приведет к тому, что GHC не будет так оптимизировать.