2015-05-18 5 views
14

У меня есть несколько файлов с разделителями на 3 ГБ. В каждом файле содержится 20 миллионов строк. Все строки должны обрабатываться независимо друг от друга, без каких-либо связей между двумя строками. Мой вопрос, что будет быстрее, А. Чтение построчно с помощью `Python: Самый быстрый способ обработки большого файла

with open() as infile: 
      for line in infile: 

Или B. Чтение файла в память в кусках и обрабатывает ее, скажем, 250 МБ в то время?

Обработка не очень сложная, я просто хватаю значение в столбце1 в List1, column2 в List2 и т. Д. Возможно, нужно добавить некоторые значения столбцов вместе.

Я использую python 2.7 в ящике Linux, который имеет 30 ГБ памяти. Текст ASCII.

Любой способ ускорить работу параллельно? Сейчас я использую прежний метод, и процесс выполняется очень медленно. Используется ли какой-либо модуль CSVReader? Мне не нужно это делать в python, приветствуются любые идеи использования языка или базы данных. Спасибо.

`

+0

многопроцессорная обработка; chunked итеративное чтение. При 3 ГБ на файл вы ** НЕ хотите читать это полностью в памяти; вы можете взорвать свои ресурсы памяти. –

+0

Похоже, что база данных поможет вам в зависимости от типа обработки, которую вы делаете. – squiguy

+0

Нет, если это задача с одним выбросом; данные в; обработка; данных вне; удалять исходные данные. –

ответ

23

Это звучит как ваш код ввода/вывода. Это означает, что многопроцессорность не поможет - если вы тратите 90% времени на чтение с диска, наличие дополнительных 7 процессов, ожидающих следующего чтения, ничего не поможет.

И при использовании модуля чтения CSV (будь то stdlib csv или что-то вроде NumPy или Pandas) может быть хорошей идеей для простоты, вряд ли это сильно повлияет на производительность.

Тем не менее, стоит проверить, что вы действительно : Ввод-вывод, а не просто гадание. Запустите свою программу и посмотрите, приближается ли ваш процессор к 0% или близко к 100% или к ядру. Сделайте то, что предложил Амадан в комментарии, и запустите свою программу всего лишь pass для обработки и посмотрите, отключится ли это 5% времени или 70%. Вы даже можете попробовать сравнить с циклом по os.open и os.read(1024*1024) или что-то в этом роде и посмотреть, будет ли это быстрее.


С вашей помощью 2.x Python, Python полагается на библиотеки C STDIO угадать, сколько буфера в то время, так что это может быть стоит заставить его в буфер больше. Самый простой способ сделать это - использовать readlines(bufsize) для некоторых крупных bufsize. (Вы можете попробовать разные цифры и измерить их, чтобы увидеть, где находится пик. По моему опыту, обычно что-либо из 64K-8MB примерно одинаково, но в зависимости от вашей системы, которая может быть другой, особенно если вы, например, читаете от сетевой файловой системы с большой пропускной способностью, но ужасной задержкой, что болотам пропускную-против-латентность реального физического диска и кэширования ОС делает)

Так, например:.

bufsize = 65536 
with open(path) as infile: 
    while True: 
     lines = infile.readlines(bufsize) 
     if not lines: 
      break 
     for line in lines: 
      process(line) 

Между тем, если вы используете 64-битную систему, вы можете попробовать использовать mmap вместо того, чтобы читать файл в первую очередь. Это, конечно, не гарантировано быть лучше, но это может быть лучше, в зависимости от вашей системы.Например:

with open(path) as infile: 
    m = mmap.mmap(infile, 0, access=mmap.ACCESS_READ) 

Python, mmap является своим родом странного объекта, он действует как str и как file в то же время, так что вы можете, например, вручную итерация сканирования для переноса строк, или вы можете позвонить readline на нем, как на файл. Оба из них потребуют большей обработки от Python, чем повторение файла в виде строк или выполнение партии readlines (потому что цикл, который будет в C, теперь находится в чистом Python ... хотя, возможно, вы можете обойти это с помощью re или с простым расширением Cython ?) ... но преимущество I/O от ОС, зная, что вы делаете с отображением, может подорвать недостаток ЦП.

К сожалению, Python не выставляет madvise вызова, который вы хотите использовать, чтобы настроить вещи в попытке оптимизировать это в C (например, явно параметр MADV_SEQUENTIAL вместо того, чтобы догадка ядра, или принуждая прозрачные огромные страницы) - но вы можете на самом деле ctypes функция из libc.

+1

Спасибо, что нашли время, чтобы ответить на это в приятной детализации :) +1 –

+0

У меня есть 30 ГБ памяти на коробке Linux. Есть ли проблема в том, что readlines() берет весь файл в память? – Reise45

+0

@ Reise45: Это зависит от того, что вы подразумеваете под «проблемой». Он должен работать_; 'readlines' на 3 ГБ-файле должен занимать менее 4 ГБ, и если вы также предварительно обработаете все строки в списках значений в памяти, это не должно превышать 12 ГБ, поэтому вы все еще находитесь в удобных пределах. Но это означает, что вы должны делать все перед чтением, так что ОС не может помочь вам подключить ваше ожидание ввода/вывода и работу вашего ЦП; вы теряете время на ошибках malloc и кеша; и т. д. Если бы была какая-то польза (например, она позволяет вам использовать NumPy для ускорения медленного цикла обработки), это может стоить того, но если нет, зачем это делать? – abarnert

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