Канал: Несколько поток потребителей

голоса
5

Я пишу программу, которая подсчитывает частоты NGrams в корпусе. У меня уже есть функция, которая потребляет поток лексем и производит NGrams из одного порядка:

ngram :: Monad m => Int -> Conduit t m [t]
trigrams = ngram 3
countFreq :: (Ord t, Monad m) => Consumer [t] m (Map [t] Int)

На данный момент я просто не могу подключить один поток потребителей к источнику потока:

tokens --- trigrams --- countFreq

Как подключить несколько потребителей потока к одному источнику потока? Я хотел бы иметь что-то вроде этого:

           .--- unigrams --- countFreq
           |--- bigrams  --- countFreq
tokens ----|--- trigrams --- countFreq
           '--- ...      --- countFreq

Плюс будет работать каждый потребитель параллельно

EDIT: Благодаря Петру I пришел к этому решению

spawnMultiple orders = do
    chan <- atomically newBroadcastTMChan

    results <- forM orders $ \_ -> newEmptyMVar
    threads <- forM (zip results orders) $
                        forkIO . uncurry (sink chan)

    forkIO . runResourceT $ sourceFile test.txt
                         $$ javascriptTokenizer
                         =$ sinkTMChan chan

    forM results readMVar

    where
        sink chan result n = do
            chan' <- atomically $ dupTMChan chan
            freqs <- runResourceT $ sourceTMChan chan'
                                 $$ ngram n
                                 =$ frequencies
            putMVar result freqs
Задан 29/07/2013 в 19:03
источник пользователем
На других языках...                            


1 ответов

голоса
5

Я предполагаю, что вы хотите, чтобы все ваши раковины получить все значения.

Я хотел бы предложить:

  1. Используйте newBroadcastTMChanдля создания нового канала Control.Concurrent.STM.TMChan(STW-чаны).
  2. Используйте этот канал , чтобы построить раковину , используя sinkTBMChanиз Data.Conduit.TMChan(STW-канала) для основного производителя.
  3. Для каждого клиента использовать dupTMChanсоздать свою собственную копию для чтения. Начать новую тему , которая будет читать эту копию , используя sourceTBMChan.
  4. Сбор результатов от ваших потоков.
  5. Убедитесь, что ваши клиенты могут читать данные так быстро, как они произведены, в противном случае вы можете получить переполнение динамической памяти.

(Я не пробовал, дайте нам знать, как это работает.)


Обновление: Один из способов , как можно собрать результаты, чтобы создать MVarдля каждого потребителя нити. Каждый из них будет putMVarего результат после того, как он закончил. И ваш основной поток будет takeMVarпо всем этим MVarс, таким образом , ожидая каждую нить , чтобы закончить. Например , если varsсписок ваших MVarс, основной поток будет выдавать mapM takeMVar varsсобрать все результаты.

Ответил 29/07/2013 в 20:08
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more