Параллельный ввод-вывод вызывает случайный вывод текста в терминале - PullRequest
4 голосов
/ 27 декабря 2011

Я использую

import Control.Concurrent.ParallelIO.Global

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

, где

processI :: Int -> IO ()

- это некоторая функция, которая считывает данные из файла, обрабатывает их и записывает в другой файл. Нет вывода на терминал. Проблема в том, что когда я запускаю программу с +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, если это имеет значение

1 Ответ

6 голосов
/ 27 декабря 2011

Буферирование, вероятно, мешает вам создать простой контрольный пример. Я смог воспроизвести его с этим (только при запуске с + RTS -Nsomething):

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

Как упоминал Томас, вам, вероятно, нужно как-то упорядочить это, хотя я не уверен, как запись в файлы изменит это. Вот простой пример того, как вы можете упорядочить это с 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

Теперь ваши записи куда-то теперь синхронизированы (stuffWriter пишет вещи по одному), и вы не должны больше ничего говорить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...