2013-05-28 6 views
1

С помощью сообщества python я начал изучать python для обработки около 500 миллионов (40G) данных и написал следующий скрипт.Как повысить производительность этого скрипта?

Входной формат файла -

Studentid,Subject,DateTime,Grade 
001,Biology,Mon Apr 25 19:32:00 PDT 2013,B 
001,Literature,Wed Apr 10 15:31:00 PST 2013,B 
001,Math,Mon Apr 22 01:32:00 PDT 2013,A 
002,Biology,Mon Apr 25 19:32:00 PDT 2013,A 
002,Math,Mon Apr 22 16:31:14 PDT 2013,C 
002,Math,Wed Apr 10 15:31:00 PST 2013,C 
003,Biology,Mon Apr 22 13:31:00 PDT 2013,A 
003,Irdu,Wed Apr 10 15:31:00 PST 2013,A 

Выходной отчет

003,Irdu;Wed Apr 10 15:31:00 PST 2013;A#Biology;Mon Apr 22 13:31:00 PDT 2013;A 
002,Math;Wed Apr 10 15:31:00 PST 2013;C#Math;Mon Apr 22 16:31:14 PDT 2013;C#Biology;Mon Apr 25 19:32:00 PDT 2013;A 
001,Literature;Wed Apr 10 15:31:00 PST 2013;B#Math;Mon Apr 22 01:32:00 PDT 2013;A#Biology;Mon Apr 25 19:32:00 PDT 2013;B 

Python Script

import csv 
import time 
import operator 
import sys, getopt 
import os 

from collections import defaultdict 
from datetime import datetime 
from operator import itemgetter 

start = time.time() 
def elapsed(): 
    return time.time() - start 

def date_key(row): 
    try: 
    formatRow = row[1].replace('PDT ','') 
    formatRow = formatRow.replace('PST ','') 
    return datetime.strptime(formatRow, "%a %b %d %X %Y") 
    except Exception, e: 
    print ("Error in sorting the date: %s \nRow : %s" % (e, row)) 
    pass 

def processRecords(accountsData, fileName): 
    for v in accountsData.itervalues(): 
    try: 
     v.sort(key=date_key) 
    except Exception, e: 
     pass 

    with open(fileName, 'a') as writer: 
    for pid,v in accountsData.iteritems(): 
     csv = '#'.join([';'.join(t) for t in v]) 
     writer.write("%s,%s\n" % (pid, csv)) 

def main(argv): 
    inputFile = '' 
    outputFile = '' 
    batchsize = 20000000 
    try: 
    opts, args = getopt.getopt(argv,"hi:o:b:",["ifile=","ofile=","bsize="]) 
    except getopt.GetoptError: 
    print 'ReportToFileBatches.py -i <inputfile> -o <outputfile> -b<batchsize>[default=20000000]' 
    sys.exit(2) 
    for opt, arg in opts: 
    if opt == '-h': 
     print 'ReportToFileBatches.py -i <inputfile> -o <outputfile> -b<batchsize>[default=20000000]' 
     sys.exit() 
    elif opt in ("-i", "--ifile"): 
     inputFile = arg 
    elif opt in ("-o", "--ofile"): 
     outputFile = arg 
    elif opt in ("-b", "--bsize"): 
     batchsize = int(arg) 

    if not (os.path.isfile(inputFile)): 
    print ("\nError : File - %s does not exist." % (inputFile)) 
    sys.exit(2) 

    #print "Batch Size %s " % batchsize 
    linenumb = 0 
    with open(inputFile,'r') as data: 
    accounts = defaultdict(list) 

    for line in data: 
     linenumb = linenumb + 1 
     line = line.rstrip('\r\n') 
     try: 
     sid, subject, datetime, grade = line.split(',') 
     accounts[sid].append((subject, datetime, grade)) 

     if (linenumb == batchsize): 
      linenumb = 0 
      processRecords(accounts, outputFile) 
      accounts = defaultdict(list) 
     else: continue 
     except Exception, e: 
     print ("Error : %s \nRow : %s" % (e, line)) 

    if(linenumb > 0): 
    processRecords(accounts, outputFile) 

    print("Total time taken - %.3fs" % elapsed()) 

if __name__ == "__main__": 
    main(sys.argv[1:]) 

Вы можете увидеть выходной файл (отчет) упорядочен по дате а также также конкатенация полей. Я трачу больше времени на сортировку столбца datetime (возможно). Я новый поклонник Python. Я очень ценю любую помощь в улучшении моего сценария, чтобы сократить время обработки. Надеюсь, у меня есть смысл.

FYI: Я уверен, что входной файл сортируется студентом и обрабатывается партиями.

+1

Я предлагаю вам использовать модуль [profile] (http://docs.python.org/3/library/profile.html#module-profile), чтобы найти ваши сценарии «горячие точки». – martineau

+2

Мне нужно пойти с мартиней на этом, профилирование - это единственный хороший путь вперед ... ваш код уже выглядит «pythonic» и использует много трюков, которые я бы предложил. Если вы просто заинтересованы в получении ускорения (а не при настройке кода), вы также можете попробовать быстро получить что-то вроде интерпретатора PyPy, но это никогда не бывает уверенным. Пожалуйста, напишите назад с результатами профиля, если вам все еще нужно больше советов. Ура! – David

+0

Профилирование не так уж сложно. См. [Как вы можете создать сценарий Python?] (Http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script). – martineau

ответ

0

Я думаю, что самое лучшее, что вы можете сделать, это pigeonhole sort. Это работает, если вы знаете границы и распространение ваших данных времени, т. Е. О самых больших и малых временах. Pigeonholing работает, разделяя ваши данные на дискретные отверстия. Например, если ваши данные распределены примерно месяц, тогда у вас может быть массив, в котором каждый индекс представляет собой массив, представляющий 1 час каждого дня этого месяца. Вы идете по списку, помещая свои данные в этот массив. Когда вы помещаете данные в этот массив, вы можете сортировать их в этом подсписке.

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

Counting sort - еще один вариант (также имеет лучшее время исполнения), но поскольку ваш файл такой большой, я думаю, что вы можете столкнуться с проблемами памяти или отстать от постоянной записи на диске. Стоит посмотреть, но будьте осторожны с этими задержками.

EDIT: Только что понял, что ваш файл имеет размер 40 г, поэтому для учета этой проблемы с памятью вместо массива массивов вы можете иметь серию файлов с известными именами, которые содержат ваши списки с голубями.

1

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

Это поражает меня как проблему с базой данных.

  1. загрузки данных в базу данных для (SQLite поставляется с питоном)
  2. добавить индекс даты
  3. дамп ваш выход

питон язык клей, чтобы сделать форматирование и анализ. Не язык для рулевого управления собственным 40G данных.

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