Это не полный ответ, но я заметил две вещи, которые я мог бы внести.
Предлагаемая улучшенная версия file_len()
. Это возвращает 0, если файл имеет нулевую длину. Ваша функция возвращает 1 для файла с нулевой длиной и 1 для файла с одной строкой.
def file_len(fname):
i = 0
with open(fname) as f:
for i, l in enumerate(f, 1):
pass
return i
Вот более быстрый способ выполнения цикла вычислений.
result = sum(e.calculate_result(i).real for i in xrange(10000) for e in element_list)
Это можно было бы сделать его еще быстрее, используя reduce()
, но я не думаю, что это может быть намного быстрее. Большая экономия с reduce()
заключается в том, что вы можете избежать связывания имен снова и снова, но нам нужно связать имя e
, поэтому мы можем позвонить e.calculate_result(i).real
, даже если тип e
может быть чем угодно.
Если вы можете сделать что-то подобное, это может быть немного быстрее.
import itertools as it
import operator as op
result = reduce(op.add, it.imap(SomeClass.calculate_something, it.product(element_list, xrange(10000))))
Опять же, основная экономия заключается в том, чтобы избежать связывания имен. it.product()
возвращает кортежи, которые включают (e, i)
, где e
является элементом от element_list
и i
является числом от xrange(10000)
. Затем it.imap()
вызовет функцию и передаст кортеж в качестве аргумента. Тогда reduce()
суммирует все. На самом деле, просто позвонить sum()
, вероятно, так же хорошо, как и reduce(op.add)
, но вы могли бы попробовать его в обоих направлениях и посмотреть, будет ли он немного быстрее, чем другой. Если вы можете найти что-то разумное для SomeClass.calculate_something
, то, возможно, вы сможете сделать эту работу.
Хмм, возможно, стоит попробовать просто дать sum()
(или reduce()
) вычислить сложную сумму, а затем выбросить мнимую часть, когда сумма будет выполнена. Будет ли это быстрее, чем доступ к атрибуту .real
один раз за значение? Я не уверен, но это может помочь вам сделать версию reduce()
.
EDIT:
Вы должны попробовать запустить программу под PyPy.
http://pypy.org/
Если вы сделаете это, не забудьте использовать эту строку вместо первого я показал:
result = sum(e.calculate_result(i).real for e in element_list for i in xrange(10000))
Таким образом, вы используете каждый элемент e
для 10000 звонков подряд , что должно помочь компилятору PyPy «точно в срок» («JIT») для получения лучшего кода. Я не знаю, поможет ли JIT только 10000 звонков или нет, но похоже, что это должен быть способ попробовать.
Какова ваша фактическая проблема? и что вы понимаете под _efficient_? – moooeeeep
Мне нужно получить доступ к этому списку в миллиард раз или более, и это _slow_. Одним из узких мест является доступ к элементам. Есть ли более питонический способ сделать это? – Ivan
Возможно, вы сможете ускорить вычисление, выполнив операции над массивом «data» numpy. Разделив данные в ** список ** экземпляров Class1.Class1, мы потеряли возможность воспользоваться numpy. Но чтобы действительно помочь вам, нам нужно будет увидеть определение 'calculate_result'. – unutbu