Это параллелизуемо? - PullRequest
2 голосов
/ 07 июля 2011

У меня огромный файл с разделителями табуляции. (10 000 предметов в виде строк и> 1 миллиона анализов в виде столбцов). У меня есть файл сопоставления, который содержит информацию, связанную с каждым из 1 миллиона столбцов. Мне нужно для каждого субъекта, для каждого анализа (для каждой ячейки) заглянуть в файл сопоставления, получить для него некоторое значение и заменить существующее значение.

В Python или Perl мне пришлось бы читать каждую строку, разбивать ее и для каждой ячейки искать в файле отображения.

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

В любом случае весь процесс циклического прохождения каждой строки или столбца занимает много времени, так как необходимо выполнить поиск каждой ячейки.

Есть ли способ, которым я мог бы распараллелить это? Как я должен думать, если я хочу распараллелить это и сделать это быстрее?

Кроме того, мне интересно узнать, как подойти к этому в стиле карты / уменьшения?

Пример файла данных выглядит следующим образом: (разделенный табуляцией)

ID  S1  S2  S3  S4  S5  
1   AA  AB  BA  BB  AB  
2   BA  BB  AB  AA  AA  
3   BA  AB  AB  AB  AB  
4   BA  AB  AB  BB  AA  
5   AA  AB  BA  BB  AB  
6   AA  BB  AB  AA  AA  
Файл отображения

выглядит следующим образом:

SID  Al_A  Al_B    
S1    A     C  
S2    G     T  
S3    C     A  
S4    G     T  
S5    A     C  

Таким образом, в файле данных, в каждой ячейке, для каждого A и B необходимо выполнить поиск в файле отображения, чтобы увидеть, на что A отображается (из столбца Al_A), и на что B отображается (на (из Столбец Al_B).

Ответы [ 2 ]

5 голосов
/ 07 июля 2011

Простой параллелизм

python parse.py assays.txt | python lookup.py mapping.txt | python reformat.py >result.txt

Где parse.py читает файл «анализов» «10000 субъектов в виде строк и> 1 миллиона анализов в виде столбцов». Он анализирует и записывает данные в стандартный вывод.

lookup.py читает отображение «получить некоторое значение для него» для заполнения внутреннего словаря. Он читает данные стандартного ввода, выполняет поиск и записывает результат в стандартный вывод.

Файл reformat.py читает stdin и переформатирует его, чтобы написать окончательный отчет, который, по-видимому, отражает структуру ввода.

Хотя это не «смущающая» параллель, она разбивает работу на тривиально параллельные этапы. Он на удивление надежный и может сбить время с процесса


Однако вам, вероятно, нужно то, что отражает смущающе параллельную природу проблемы. Существует 10 000 * 1 000 000 == 10 миллиардов отдельных значений, которые кажутся полностью независимыми.

Другой (более сложный) подход заключается в следующем. Это зависит от http://docs.python.org/library/multiprocessing.html.

  1. Простой читатель Process разбивает входной файл, записывая записи в n различных Queue с. Это означает, что каждый Queue получает 10 000 / n записей. n может быть большим числом от 10 до 100. Да. 100 очередей, каждая из которых получает 100 записей. Ничего страшного, если они ждут, чтобы их запланировали на ничтожных ядрах на вашем сервере. Ядра будут на 100% заняты. Это хорошо.

  2. Каждый из n Queue обслуживается рабочим Process, который выполняет поиск для каждого анализа в записи и помещает полученную запись в вывод Queue , Вы можете настроить n на самые разные значения, чтобы увидеть, что произойдет. В какой-то момент большее количество работников замедлит работу. Трудно предсказать, где находится этот уровень, поэтому экспериментируйте.

  3. Вывод Queue считывается рабочим Process, который просто форматирует выходной файл из того, что он находит в очереди.

Это означает, что вам нужен какой-то объект "Assay", который вы можете сериализовать из входного файла и поместить в Python

1 голос
/ 07 июля 2011

Поскольку я понимаю вашу проблему, каждая из ваших ячеек данных не зависит от других, учитывая, что существует действительно простой способ распараллелить это без изменения какого-либо существовавшего ранее кода. Все, что вам нужно сделать, - это предварительно обработать файлы данных с помощью команды, подобной split инструменту командной строки. Затем обработайте каждый из файлов параллельно с любым существующим ранее кодом. Наконец, объедините их всех вместе в конце.

Вот пример команд, которые вы, возможно, захотите выполнить:

split -l 100 data_file.tsv data_
ls data_* | xargs -L 1 perl your_processing_file.pl
cat output_* > total_output
rm output_*

Предполагается, что ваш скрипт возьмет файл с именем data_ $ x и создаст новый файл с выходным именем output_ $ x, для этого вам, возможно, придется слегка его изменить.

На самом деле это очень распространенный подход к распараллеливанию такой проблемы.

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