2014-11-04 4 views
3

Мне очень нравится концепция трубопровода/труб для применения операций с потоковым источником ввода-вывода. Мне интересно создавать инструменты, которые работают с очень большими файлами журнала. Одна из достопримечательностей перехода на Haskell из Python/Ruby - это более простой способ написания параллельного кода, но я не могу найти документацию об этом. Как я мог настроить поток канала, который считывает строки из файла и работает на них параллельно (т. Е. С 8 ядрами, он должен читать восемь строк и передавать их на восемь различных потоков, которые нужно обработать, а затем снова собирать и т. д.), в идеале с минимальной «церемонией», как это возможно ...Параллельная обработка в потоке трубопровода

Возможно, можно указать, должны ли линии соединяться по порядку или нет, если это может повлиять на скорость процесса?

Я уверен, что можно было бы что-то соблазнить собой, используя идеи из книги Parallel Haskell, но мне кажется, что выполнение чистой функции параллельно (parmap и т. Д.) В середине рабочего процесса Conduit должно быть очень легко?

+1

В общем, концепция трубопроводов (и труб) предназначена для последовательного, а не параллельного. В частности, когда канал запрашивает ввод, только тогда его восходящий канал запускается для получения одного значения. Поэтому распараллеливать нечего. То, что вы можете сделать, - это создать канал, который находится во внутреннем распараллеливании - прием входных данных, планирование задач для их обработки и выход их. –

+1

Я просто нахожу это странным, так как многие сторонники Haskell отмечают возрастающую важность многоядерных процессоров и как Haskell как чистый функциональный язык действительно сияет в этом отношении. И всякий раз, когда вы говорите о том, чтобы делать вещи с очень большими объемами данных в Haskell, кабелепровод и труба упоминаются как лучшие рамки. Поэтому я бы подумал, что распараллеливание обработки в трубе/трубопроводе должно быть «тривиальным» ... –

+1

Существует два разных понятия: [параллелизм и параллелизм] (https://www.haskell.org/haskellwiki/Parallelism_vs. _Concurrency) (Я должен был сделать это различие более ясным в своем первом комментарии). Параллелизм естественен в чистых языках и не зависит от какой-либо структуры, вы просто запускаете несколько искры для вычисления чистых функций на нескольких ядрах, например, в канале. С другой стороны, параллелизм (многопоточность) является явным и недетерминированным и концептуально отличается от каналов/труб. –

ответ

6

В качестве примера «внутреннего параллелизма» упоминается Петр Pudlák в своем комментарии, считают эту функцию (я использую pipes, но может быть реализован с conduit так же легко):

import Control.Monad 
import Control.Lens (view) 
import Control.Concurrent.Async (mapConcurrently) 
import Pipes 
import qualified Pipes.Group as G 
import qualified Control.Foldl as L 

concProd :: Int -> (a -> IO b) -> Producer a IO r -> Producer b IO r 
concProd groupsize action producer = 
     L.purely G.folds L.list (view (G.chunksOf groupsize) producer) 
     >-> 
     forever (await >>= liftIO . mapConcurrently action >>= mapM G.yield) 

Этот функция принимает в качестве параметров размер группы, действие, которое мы хотим запустить для каждого значения типа a, и значение Producer значений a.

Он возвращает новый Producer. Внутренне производитель считывает значения a партиями groupsize, обрабатывает их одновременно и дает результаты один за другим.

Код использует Pipes.Group, чтобы «разделить» оригинального производителя на суб-производителей размером groupsize, а затем Control.Foldl, чтобы «свернуть» каждого субпродюсера в список.

Для более сложных задач вы можете обратиться к асинхронным каналам, предоставленным pipes-concurrency или stm-conduit. Но они вытаскивают вас из «единого трубопровода» мировоззрения ванильных труб/трубопроводов.

+0

Это красиво. Огромное спасибо! Я подумывал об этом некоторое время, и кажется, что Pipes.Group дает естественный способ группировать поток трубы в куски и работать над ними параллельно. У меня никогда не было идеи использовать «чисто складной список» для создания кусков. Очень приятно! – Stephan

 Смежные вопросы

  • Нет связанных вопросов^_^