Мои коды Python в целом очень медленные, это нормально?

1

Недавно я начал самообучающийся python и использовал этот язык для онлайн-курса в алгоритмах. По некоторым причинам многие из моих кодов, которые я создал для этого курса, очень медленные (относительно кодов Matlab C/С++, которые я создал в прошлом), и я начинаю беспокоиться о том, что я не правильно использую python.

Вот простой код python и matlab, чтобы сравнить их скорость.

MATLAB

   for i = 1:100000000
        a = 1 + 1
   end 

Python

   for i in list(range(0, 100000000)):
        a=1 + 1

Код matlab занимает около 0,3 секунды, а код python занимает около 7 секунд. Это нормально? Мои коды python для сложных задач очень медленные. Например, как назначение HW, я запускаю глубину первого поиска на графике с около 900000 узлов, и это происходит навсегда. Спасибо.

  • 2
    Какую версию Python вы используете? range ведет себя по-разному между Py2 и Py3. Кроме того, в данном конкретном случае нет необходимости заключать range list .
  • 0
    Также, если переменная i не используется, вы можете использовать _ (подчеркивание) вместо i.
Показать ещё 1 комментарий
Теги:
performance

3 ответа

3
Лучший ответ

Производительность не явная цель дизайна Python:

Не слишком беспокоитесь о производительности - планируйте оптимизировать позже, когда необходимо.

Это одна из причин, почему Python интегрирован с большим количеством высокопроизводительных вычислительных бэкэнд-движков, таких как numpy, OpenBLAS и даже CUDA, просто чтобы назвать некоторые из них.

Лучший способ пойти вперёд, если вы хотите повысить производительность, - это позволить высокопроизводительным библиотекам делать тяжелую работу для вас. Оптимизация циклов внутри Python (с использованием xrange вместо диапазона в Python 2.7) не даст вам очень впечатляющих результатов.

Вот немного кода, который сравнивает разные подходы:

  • Ваш оригинальный list(range())
  • Предлагает использовать xrange()
  • Выход из i out
  • Использование numpy для добавления с использованием массива numpy (добавление вектора)
  • Использование CUDA для добавления векторов на графический процессор

код:

import timeit
import matplotlib.pyplot as mplplt

iter = 100
testcode = [
    "for i in list(range(1000000)): a = 1+1",
    "for i in xrange(1000000): a = 1+1",
    "for _ in xrange(1000000): a = 1+1",
    "import numpy; one = numpy.ones(1000000); a = one+one",
    "import pycuda.gpuarray as gpuarray; import pycuda.driver as cuda; import pycuda.autoinit; import numpy;" \
    "one_gpu = gpuarray.GPUArray((1000000),numpy.int16); one_gpu.fill(1); a = (one_gpu+one_gpu).get()"
    ]
labels = ["list(range())", "i in xrange()", "_ in xrange()", "numpy", "numpy and CUDA"]

timings = [timeit.timeit(t, number=iter) for t in testcode]

print labels, timings

label_idx = range(len(labels))
mplplt.bar(label_idx, timings)
mplplt.xticks(label_idx, labels)
mplplt.ylabel('Execution time (sec)')
mplplt.title('Timing of integer addition in python 2.7\n(smaller value is better performance)')
mplplt.show()

Результаты (график) выполнялись на Python 2.7.13 на OSX: Изображение 174551

Причина, по которой Numpy работает быстрее, чем решение CUDA, заключается в том, что накладные расходы на использование CUDA не влияют на эффективность Python + Numpy. Для больших вычислений с плавающей запятой CUDA делает даже лучше, чем Numpy.

Обратите внимание, что решение Numpy работает в 80 раз быстрее, чем ваше оригинальное решение. Если ваши тайминги верны, это будет даже быстрее, чем Matlab...

Последняя заметка о DFS (Depth-afirst-Search): здесь - интересная статья о DFS в Python.

2

Попробуйте использовать xrange вместо range.

Разница между ними заключается в том, что **xrange** генерирует значения по мере их использования вместо range, который пытается сгенерировать статический список во время выполнения.

  • 1
    При условии, что он использует Python 2
  • 0
    Ага. Если он использует Python 3, диапазон должен быть в порядке.
Показать ещё 1 комментарий
0

К сожалению, потрясающая гибкость и легкость питона зависит от того, что он медленный. А также для таких больших значений итерации я предлагаю использовать модуль itertools, поскольку он имеет более быстрое кэширование.

xrange - хорошее решение, однако, если вы хотите итерации по словарям и тому подобное, лучше использовать itertools, как в этом, вы можете перебирать любой объект последовательности.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню