2012-02-07 6 views
7

Я пишу многопоточный декомпрессор в python. Каждый поток должен получить доступ к другому фрагменту входного файла.Чтение одного файла из нескольких потоков в python

Примечание 1: невозможно загрузить весь файл, поскольку он колеблется от 15 ГБ до 200 ГБ; Я не использую многопоточность для ускорения чтения данных, но декомпрессии данных, я просто хочу убедиться, что чтение данных не замедляет декомпрессию.

Примечание 2: GIL не является проблемой, поскольку главная функция декомпрессора является расширением C и вызывает Py_ALLOW_THREADS, так что GIL освобождается при распаковке. Декомпрессия второй ступени использует numpy, который также не является GIL-бесплатным.

1) Я предполагал, что это не будет работать, чтобы просто поделиться объект декомпрессор (который в основном оборачивает объект файла), так как если поток А вызывает следующее:

decompressor.seek(x) 
decompressor.read(1024) 

и нити B делает то же самое, нить A может закончиться чтением из коррекции потока B. Это верно?

2) Прямо сейчас я просто создаю каждый поток, создавая свой собственный экземпляр Decompressor, и, похоже, он работает, но я не уверен, что это лучший подход. Я рассмотрел эти возможности:

  • Добавить что-то вроде

    seekandread(from_where, length) 
    

    к классу декомпрессор, который приобретает замок, ищет, читает и освобождает замок;

  • Создайте поток, который ждет запросов на чтение и выполняет их в правильном порядке.

Итак, у меня отсутствует очевидное решение? Существует ли существенная разница в производительности между этими методами?

Благодаря

+5

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

+0

Невозможно загрузить весь файл, поскольку он колеблется от 15 Гб до 200 Гб; Я не использую многопоточность для ускорения чтения данных, но декомпрессии данных, я просто хотел убедиться, что чтение данных не замедляет декомпрессию. – Alberto

+0

Конечно, это может быть или не относится к твердотельным накопителям. Однако я понятия не имею о предмете. Вы не должны ретранслировать оборудование, чтобы это сделать. Как только SSD достаточно распространены, выполнение ввода-вывода в многопоточном режиме может быть эффективным. –

ответ

2

Вы можете использовать mmap. mmap() vs. reading blocks

Как отмечает Тим ​​Купер, mmap - это хорошая идея, когда у вас есть случайный доступ (несколько потоков могут показаться вам похожими), и они смогут делиться одними и теми же физическими страницами.

+0

Это кажется отличным! Я просмотрел документацию python для mmap, но я не смог найти ссылку на информацию о безопасности потоков. Если 2 потока выполняют что-то вроде файла = mappedfile [x: y] в одно и то же время, будет ли он работать, как ожидалось? – Alberto

+0

Чтобы ответить на вопрос, кажется, что нотация фрагмента python mmap фактически является потокобезопасной. Я создал тестовую программу, которая обращается к различным частям mmapped файла из разных потоков и проверяет результат. Он проходит тест, если я использую нотацию среза, он терпит неудачу, если я использую поиск/чтение. Тем не менее, мне все равно нужно проверить производительность. – Alberto

+1

@Alberto: Мне кажется, что любой отредактированный сегмент, который уже обрабатывается, должен быть защищен хотя бы мьютексом, если не металическим условным семафором. С помощью условного семафора бросания я имею в виду семафор, который не дожидается, если условие предварительного ввода не будет выполнено до тех пор, пока оно не появится, но вместо этого выдает исключение. Это гибрид между семафором и гауром. Вы можете захотеть выбросить только тогда, когда условие B не будет выполнено, и подождите, если будет выполнено условие A. –

2

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

+0

Спасибо, я посмотрю на это. – Alberto

1

CPython имеет GIL, поэтому несколько потоков не увеличивают производительность для задач, связанных с процессором.

Если проблема не связана с IO (диск обеспечивает/сохраняет данные быстрее, чем процессор распаковывает их), вы можете использовать multiprocessing module: каждый процесс открывает файл и распаковывает заданный диапазон байтов.

+1

Основная функция декомпрессора является расширением C и вызывает Py_ALLOW_THREADS, так что GIL освобождается при распаковке. Декомпрессия второй ступени использует numpy, который также не содержит gil. Я уже измерил хорошее ускорение. – Alberto

+0

(возможно, это разъяснение - о вас «позаботились» о GIL - также могли бы зайти в основной вопрос) – jsbueno

+0

Вы правы, сделано – Alberto

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