Присоединение к параллельному выводу Python - PullRequest
8 голосов
/ 17 февраля 2011

Я использую что-то вроде этого:

find folder/ | xargs -n1 -P10 ./logger.py > collab

Внутри logger.py Я обрабатываю файлы, выводя отформатированные строки. Так что коллаб должен выглядеть как

{'filename' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}

Вместо этого иногда строки перемешиваются:

{'filename' : 'file1', 'size' : 1000}
{'file
{'filename' : 'file1', 'size' : 1000}
name' : 'file1', 'size' : 1000}
{'filename' : 'file1', 'size' : 1000}

Как я могу предотвратить / исправить это?

Ответы [ 3 ]

2 голосов
/ 17 февраля 2011

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

Наиболее распространенной причиной этого является буферизация ввода / вывода в Python или libc. Например, это может быть буферизация 16 Кбайт вывода, а затем запись всего блока сразу. Вы можете уменьшить это, сбросив стандартный вывод после записи на него, но это неудобно. Теоретически, вы должны иметь возможность передать -u Python, чтобы отключить буферизацию стандартного вывода, но это не сработало, когда я попробовал. См. Ответ Себастьяна на Отключить буферизацию вывода для более общего решения (хотя, возможно, есть способ отключить буферизацию вывода более напрямую).

Вторая проблема заключается в том, что базовые записи не всегда атомарны. В частности, записи в каналы являются только атомарными до определенного размера (PIPE_BUF, обычно 512 байт); выше этого не гарантировано. Это строго относится только к каналам (не к файлам), но применяются те же общие проблемы: меньшие записи чаще происходят атомарно. Смотри http://www.opengroup.org/onlinepubs/000095399/functions/write.html.

1 голос
/ 17 февраля 2011

Проблема в том, что выходные данные из xargs смешаны вместе.GNU Parallel создан для решения этой проблемы.По умолчанию это гарантирует, что вывод не смешан вместе.Так что вы можете просто сделать это:

find folder/ | parallel ./logger.py > collab

Это запустит один logger.py на процессор.Если вы хотите 10:

find folder/ | parallel -P10 ./logger.py > collab

Посмотрите интровидео, чтобы узнать больше о GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ

1 голос
/ 17 февраля 2011

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

И все равно это не весело. Как насчет передачи выходных данных из xargs (таким образом вы получите сплошные порции вывода вместо потока вывода, который разбит), а затем как-то объедините эти порции?

...