我想在Haskell中同时从控制台上的两个不同功能打印实时输出。
有可能吗?
您可以使用此代码...
import Control.Parallel
main = a `par` b `par` c `pseq` print (a + b + c)
where
a = ack 3 10
b = fac 42
c = fib 34
fac 0 = 1
fac n = n * fac (n-1)
ack 0 n = n+1
ack m 0 = ack (m-1) 1
ack m n = ack (m-1) (ack m (n-1))
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
我希望a和b在不同的内核上同时计算,并同时在控制台上打印它们的进度。
答案 0 :(得分:2)
您可以通过使用print
生成两个线程来运行两个并发的forkIO
操作。每个线程计算并打印自己的输出,然后向主线程发出终止信号。
例如:
main :: IO ()
main = do
v1 <- newEmptyMVar
v2 <- newEmptyMVar
forkIO $ do
print (10+4)
putMVar v1 ()
forkIO $ do
print (20+5)
putMVar v2 ()
-- wait for the threads
takeMVar v1
takeMVar v2
请注意:
输出可能同时发生。即使不太可能,输出字符串14
和25
也可能被交错为1245
。一个人应该使用另一把锁来防止这种情况。
两个Haskell线程可以在不同的内核或同一内核上运行。如果计算时间很长,那么我们使用的是线程RTS(使用-threaded
进行编译),并且如果我们指定了足够的内核(使用类似./myExe +RTS -N2 -RTS
的可执行文件,则仅使用-N
将选择所有可用的内核),RTS应该使用多个内核。
在这里,在得到的两个线程中计算fib 38
和fib 39
:
$ time ./ParallelExample ; time ./ParallelExample +RTS -N2 -RTS
39088169
63245986
real 0m9.094s
user 0m9.076s
sys 0m0.020s
39088169
63245986
real 0m5.823s
user 0m9.532s
sys 0m0.040s
在第一个测试中,两个Haskell线程在同一OS线程之上运行,大约只使用一个内核。