Haskell 并行IO导致终端中的随机文本输出

Haskell 并行IO导致终端中的随机文本输出,haskell,concurrency,parallel-processing,Haskell,Concurrency,Parallel Processing,我正在使用 import Control.Concurrent.ParallelIO.Global main = parallel_ (map processI [1..(sdNumber runParameters)]) >> stopGlobalPool 在哪里 是一个函数,它从文件中读取数据,处理数据并将其写入另一个文件没有输出到终端。问题是当我使用+RTS-N8运行程序时,终端充满了随机文本,如 piptufuht teata thtsieieo ocnsno e ns

我正在使用

import Control.Concurrent.ParallelIO.Global

main = parallel_ (map processI [1..(sdNumber runParameters)])  >> stopGlobalPool
在哪里

是一个函数,它从文件中读取数据,处理数据并将其写入另一个文件没有输出到终端。问题是当我使用
+RTS-N8
运行程序时,终端充满了随机文本,如

piptufuht teata thtsieieo ocnsno e nscsdeoe qnqvuduee   ernvnstetiirioasanlil lolwynya. .s
w
a s s uY Ysosopuuue's'nvpvdeeee n dpdp rerdodoub beada
bub lel y
发生了什么事?没有+RTS,就没有混乱。我无法用一个更简单(适合在这里发布)的程序重现这种行为


GHC 7.0.3如果这很重要的话,缓冲可能会阻止您构建简单的测试用例。我能够用这个复制它(只有在使用+RTS-Nsomething运行时):

正如Thomas提到的,您可能需要以某种方式对其进行排序,尽管我不确定直接写入文件将如何改变这一点。下面是一个简单的示例,您可以使用
Chan
对其进行排序。我相信有更好的方法可以做到这一点,这只是一个例子,说明我是如何做到这一点,以避免输出混乱

import Control.Concurrent
import Control.Concurrent.Chan
import System.IO

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering

    ch <- newChan            -- Things written here are picked up by stuffWriter
    forkIO $ stuffWriter ch  -- Fire up concurrent stuffWriter

    forkIO $ writeChan ch "foo"
    forkIO $ writeChan ch "bar"
    forkIO $ writeChan ch "baz"
    threadDelay 1000         -- Allow things to print

-- | Write all the things!
stuffWriter :: Chan String -> IO ()
stuffWriter ch = do
    readChan ch >>= putStrLn -- Block, then write once I've got something
    stuffWriter ch           -- loop... looking for more things to write
导入控制。并发
进口管制.Concurrent.Chan
导入系统.IO
main::IO()
main=do
hSetBuffering标准输出无缓冲
CHIO()
填充器ch=do
readChan ch>>=putStrLn--Block,一旦我有了什么东西就写
循环。。。想写更多的东西吗

现在,您对某处的写入现在是同步的(
stuffWriter
一次写入一个内容),您不应该再出现乱码了。

您没有说明是否将文本输出到终端。来自不同线程的文本可能会交织在一起,您必须序列化终端IO,通常通过选择单个线程进行打印。我认为有一个软件包正是为了这个目的,但这两种方法都不难。@ThomasM.DuBuisson:IIRC,
putStr
获得句柄上的锁,因此它应该是原子的。然后可能是
stderr
,而不是
stdout
,被淹没了。不同的
processI
s尝试写入同一个文件吗?@DanielFischer可能他收到了乱码的错误/警告消息?哦,是的,它们是警告。Data.Array.Repa与Parallel.IO冲突。它没有影响实际输出(写入的文件),只是产生了大量扭曲的警告。您是否了解我的程序中没有输出到终端(即没有putStrLn)?是的,写入文件和终端应该非常相似,因为putStr/putStrLn只是hPutStr的一个特例(带有隐式stdout文件句柄),这个概念还是一样的。。。如果您向一个
Chan
写入内容,并且从中读取的函数是同步运行的,那么任何由于并发或并行性而给您带来麻烦的问题都应该得到解决,因为现在一次只完成一件事情。您能解释(或提供链接)什么是通过+RTS输出到终端的吗?这些随机文本是从哪里来的?我明白了。。。你在哪儿写字?如果是,即使使用+RTS运行,您要写入的文件是否仍然正确生成?你只是有多余的垃圾出现在候机楼?
import Control.Concurrent
import System.IO

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering
    forkIO $ putStrLn "foo"
    forkIO $ putStrLn "bar"
    forkIO $ putStrLn "baz"
    threadDelay 1000    -- Allow things to print
import Control.Concurrent
import Control.Concurrent.Chan
import System.IO

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering

    ch <- newChan            -- Things written here are picked up by stuffWriter
    forkIO $ stuffWriter ch  -- Fire up concurrent stuffWriter

    forkIO $ writeChan ch "foo"
    forkIO $ writeChan ch "bar"
    forkIO $ writeChan ch "baz"
    threadDelay 1000         -- Allow things to print

-- | Write all the things!
stuffWriter :: Chan String -> IO ()
stuffWriter ch = do
    readChan ch >>= putStrLn -- Block, then write once I've got something
    stuffWriter ch           -- loop... looking for more things to write