Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Ubuntu上Haskell(GHC)中的线程延迟问题_Linux_Haskell_Ubuntu - Fatal编程技术网

Linux Ubuntu上Haskell(GHC)中的线程延迟问题

Linux Ubuntu上Haskell(GHC)中的线程延迟问题,linux,haskell,ubuntu,Linux,Haskell,Ubuntu,在我的一些机器上,我注意到GHC.Conc中threadDelay函数的奇怪行为。以下节目: main = do print "start" threadDelay (1000 * 1000) print "done" 按预期运行需要1秒。另一方面,该计划: {-# LANGUAGE BangPatterns #-} import Control.Concurrent main = do print "start" loop 100

在我的一些机器上,我注意到GHC.Conc中threadDelay函数的奇怪行为。以下节目:

main = do print "start"
          threadDelay (1000 * 1000)
          print "done"
按预期运行需要1秒。另一方面,该计划:

{-# LANGUAGE BangPatterns #-}
import Control.Concurrent

main = do print "start"
          loop 1000
          print "done"
  where loop :: Int -> IO ()
        loop !n =
          if n == 0 
          then return ()
          else do threadDelay 1000
                  loop (n-1)
在我的两台机器上运行大约需要10秒,但在其他机器上运行大约需要1秒,正如预期的那样。(我用“-threaded”标志编译了上述两个程序。)下面是Threadscope的屏幕截图,显示每10毫秒只有一次活动:

另一方面,下面是我的一台机器上ThreadScope的屏幕截图,该程序总共耗时1秒:

类似的C程序:

#include <unistd.h>
#include <stdio.h>

int main() {
  int i; 
  for (i=1; i < 1000; i++) {
    printf("%i\n",i);
    usleep(1000);
  }
  return 0;
}

以前是否有人遇到过此问题,如果是,如何解决此问题?我在所有机器上运行ghc 7.2.1 for Linux(x86_64),并且运行各种版本的Ubuntu。它在Ubuntu 10.04.2上运行不好,但在11.04上运行良好。

threadDelay
不是一个精确的计时器。它承诺你的线程将睡眠至少和它的论点所说的一样长,但它没有承诺更多。如果你想让某些事情周期性地发生,你就必须使用其他的东西。(我不确定是什么,但可能对您有用。)

我怀疑您忘记了使用“-threaded”选项进行编译。(我曾经在6.12.3中这样做过一次,并且始终有30毫秒的线程延迟。)

如上所述,threadDelay只提供一个保证,即您至少会等待您请求的时间。Haskell的运行时没有获得操作系统的特殊合作

除此之外,这是操作系统的最大努力

这可能值得为线程延迟测试您的结果。例如:

module Main where
import Control.Concurrent
import Data.Time

time op = 
    getCurrentTime >>= \ t0 -> 
    op >> 
    getCurrentTime >>= \ tf -> 
    return $! (diffUTCTime tf t0)

main :: IO ()
main = 
    let action tm = time (threadDelay tm) >>= putStrLn . show in
    mapM action [2000,5000,10000,20000,30000,40000,50000] >>
    return ()
在我的windows box上,这为我提供了:

0.0156098s 0.0156098s 0.0156098s 0.0312196s 0.0312196s 0.0468294s 0.0624392s 0.0156098s 0.0156098s 0.0156098s 0.0312196s 0.0312196s 0.0468294s 0.0624392s 这表明delay和getCurrentTime的组合具有15.6毫秒的分辨率。当我循环1000次延迟1000时,我会等待15.6秒,所以这只是线程的最小等待时间

在我的UbuntuBox(11.04,内核2.6.38-11)上,我获得了更高的精度(~100us)

您可以通过让程序更繁忙来避免时间问题,这样我们就不会切换上下文。无论哪种方式,我都建议您不要使用threadDelay进行计时,或者至少检查时间并在给定的瞬间执行任何操作

如果你愿意使用FFI,通过C实现的高精度睡眠可能对你有用,但代价是你需要使用绑定线程(至少对你的计时器是这样)

0.0156098s 0.0156098s 0.0156098s 0.0312196s 0.0312196s 0.0468294s 0.0624392s