Найти - Пользователи
Полная версия: code review Ребят подскажите как ускорить выполнение программы
Начало » Python для новичков » code review Ребят подскажите как ускорить выполнение программы
1
yalumea
Всем доброго времени суток
Написал программку, но меня не устраивает время выполнения, хотелось бы побыстрее.
Полагаю есть несколько способов как ускорить:
- Запускать в какой-то среде разработки или в консоли(я запускал в текстовом редакторе Sublime)
- Подключить какую-то библиотеку, чтоб распаралелить выполнение(в процессе выполнения, у меня, было задействовано одно ядро, процессор грузился в среднем на 17-18 %)
- Улучшить код программы
- Возможно что-то еще, о чем даже не знаю что такое может быть)
 import os
import pandas as pd 
#digit from str
def extract_deg(input_str): 
	if input_str is None or input_str == '': return 0 
	out_number = '' 
	f = 0
	for ele in input_str: 
		if ele.isdigit() or ele == '-': 
			out_number += ele
		elif ele == ',':
			out_number += '.'
			f = 1
	if f == 1:
		out_number = (float(out_number))
	else: 
		out_number = (int(out_number))
	return (out_number)
frame = pd.DataFrame()
af = os.listdir(path=".")
nf = af[10:-5]
for i in nf:
	frame = frame.append(pd.read_csv(i), ignore_index=True)
frame.to_csv("datatest.csv", encoding='utf-8', sep='\t', index=False)
frame['minmax'] = frame['MAX'] - frame['MIN']
#массивы переменных
dlst = ['dvar1', 'dvar2', ..., 'dvar11'] 
slst = ['svar1', 'svar2', ..., 'svar20']
elst = ['evar1', 'evar2', ..., 'evar44']
blst = ['year', 'mounth', 'day', 'hh', 'mm']
sls = []
for i in slst:
	exec(i + ' = []')
	exec('sls.append('+i+')')
els = []
for i in elst:
	exec(i + ' = []')
	exec('els.append('+i+')')
bls = []
for i in blst:
	exec(i + ' = []')
	exec('bls.append('+i+')')
print(len(frame))
for i in range(len(frame)):
	year.append(int(str(frame['DATE'][i])[:4]))
	mounth.append(int(str(frame['DATE'][i])[4:6]))
	day.append(int(str(frame['DATE'][i])[6:8]))
	hh.append(int(str(frame['TIME'][i])[:2]))
	mm.append(int(str(frame['TIME'][i])[2:4]))
	time = [year[i], mounth[i], day[i], hh[i], mm[i], 0]
	print(i, end=' ')
	#def1, def2 собирают текстовые данные, из которых, 
	#при помощи extract_deg вытаскиваются числовые значения
	for p in range(len(dlst)-1):
		l = (def1(dlst[p], time))
		sls[p*2].append(l[0])
		sls[(p*2)+1].append(l[1])
	for p in range(len(dlst)):
		l = (def2(dlst[p], time))
		els[p*4].append(l[0])
		els[(p*4)+1].append(l[1])
		els[(p*4)+2].append(l[2])
		els[(p*4)+3].append(l[3])
alllst = sls + els + bls
salllst = slst + elst + blst
for i in range(len(alllst)):
	frame[salllst[i]] = pd.Series(alllst[i])
frame.to_csv("data.csv", encoding='utf-8', sep='\t', index=False)

Пока вы это читаете, сделаю чтоб результат выводился не в конце выполнения программы, а к примеру каждые 10000 строк датафрейма)
FishHook
yalumea
for i in slst:
exec(i + ' = ')
exec('sls.append('+i+')')

Что это, Куча? Что это?
doza_and
yalumea
- Запускать в какой-то среде разработки или в консоли(я запускал в текстовом редакторе Sublime)
Это практически не влияет на скорость.
yalumea
- Подключить какую-то библиотеку, чтоб распаралелить выполнение(в процессе выполнения, у меня, было задействовано одно ядро, процессор грузился в среднем на 17-18 %)
Перед этим надо выяснить что тормозит программу. Выяснить это по приведенным вами данным нельзя, поскольку вы не привели входных данных.
yalumea
- Улучшить код программы
Что это?
yalumea
- Возможно что-то еще, о чем даже не знаю что такое может быть)
Основной способ вы не назвали - оптимизация алгоритма. Да для питона важно выносить вычислительно сложные части во внешние модули расширения (которые компилируются и оптимизированы).

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

Очевидно код содержит дичь
yalumea
year.append(int(str(frame)))
Такие штуки очевидно неффективны
yalumea
exec('bls.append('+i+')')
Тут вам бы массивы использовать
yalumea
def extract_deg(input_str):
функция не используется.

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

Вам надо написать что вы хотите сделать и привести пример данных.
yalumea
FishHook
 for i in slst:
	exec(i + ' = []') # Объявление переменных из списка названий переменных
	exec('sls.append('+i+')') #Запись переменных в список, чтобы потом можно было обращаться к каждой переменной в цикле

yalumea
doza_and
yalumea
def extract_deg(input_str):
функция не используется.
функция используется по несколько раз в других функциях, т.к. они собирают данные в текстовом виде, и данная функция вызывается, чтобы вытащить числовые значения из текста
doza_and
yalumea
exec('bls.append('+i+')')
Тут вам бы массивы использовать
Не знаю как на Питоне использовать массивы, поэтому пользуюсь списками
doza_and
Очевидно код содержит дичь
yalumea
year.append(int(str(frame)))
Такие штуки очевидно неффективны
Я бы рад сделать это без цикла как-то так:
 frame['year'] = frame['<DATE>'][:4] 
но у меня не получается. В этом месте на входе Series из дат вида 20171221, и я пытаюсь их поделить на год, месяц и день
doza_and
Какое это время? Сколько у вас данных, какая скорость вам нужна? Может ваши желания несбыточны и возиться нет смысла.
На данный момент в датафрейме 2948265 строк, в каждую строку добавляется по 69 новых записей, все это выполняется за 2,5 дня
Спасибо за наводящие вопросы, алгоритм так понял если получится улучшить, то не значительно, поэтому остается распаралелить выполнение основного цикла
doza_and
У вас наверное неверное представление о том что такое питон. Это способ вызвать готовые высокоуровневые функции реализованные на С. А сами команды питоном не особо быстро выполняются.
yalumea
функция используется по несколько раз в других функциях,
В вашем фрагменте кода нет ее вызова.

И тем более вы не написали что вы собственно делаете. Я не вижу вашем коде ничего кроме совершенно неуместного и неэффективного парсинга литералов функцией extract_deg и набивания каких-то списков.


Вам надо привести пример данных и описать что вы хотите.


По моим оценкам Обработка трех миллионов записей в один поток займет от силы 2-3 минуты

например:
 import datetime
import time
lit=["20170820"]*3000000
t0 = time.perf_counter()
[datetime.datetime.strptime(i, '%Y%m%d') for i in lit]
t1 = time.perf_counter()
print(t1-t0)
31
те оценка времени по порядку - минуты.



py.user.next
yalumea
- Улучшить код программы
Чтобы улучшить код программы, нужно сначала её полностью придумать без всякого кода. Потом её нужно продумать без всякого кода. И вот когда она уже вся придумана и продумана, можно будет её записывать в виде кода.

Чтобы это всё делать, нужно изучать программирование во всех его аспектах. Лёгкое поверхностное изучение питона не даст тебе ничего, так как язык программирования программу не делает. Язык программирования позволяет программу только записать, как кисти и краски позволяют художнику только записать картину из своего воображения или как карандаш позволяет музыканту только записать ноты произведения из своего воображения.
PEHDOM
yalumea
меня не устраивает время выполнения, хотелось бы побыстрее.
Я бы начал с профилирования чтобы выяснить узкие места в коде и уже смотреть можно ли их оптимизировать и если можно то как.
Ну и кроме уже указаных выше рекомендаций по оптимизации самого алгоритма есть боле общие рекомендации, например убрать повторяющиеся операции. Возьмем ваш код:
 ...
for i in range(len(frame)):
	year.append(int(str(frame['DATE'][i])[:4]))
	mounth.append(int(str(frame['DATE'][i])[4:6]))
	day.append(int(str(frame['DATE'][i])[6:8]))
...
вы три раза выполняете одну и туже операцию :
 (str(frame['DATE'][i])
берете элемент словаря потом какойто индекс из списка и преобразовываете в строку. и это все в цикле из kk строк. Еестественно интерпретатор тратит на это время и вычислительные мощности, хотя если сделать например так:
 ...
for i in range(len(frame)):
    str_date = str(frame['DATE'][i])
    year.append(int(str_date[:4]))
    mounth.append(int(str_date[4:6]))
    day.append(int(str_date[6:8]))
...
то по идее оно ускорит вашу программу на какойто (долю)процент. и таких кусков у вас несколько.
При этом я не уверен что имеет смысл приводить все к строке, по идее если вы читаете из файла то оно вам уже возвращает строки, но тут ХЗ может пандас прводит к дате при чтении.


This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB