Производительность Python - вам когда-нибудь приходилось переписывать что-то еще? - PullRequest
44 голосов
/ 22 декабря 2008

Кто-нибудь когда-нибудь имел код на Python, который оказался недостаточно быстрым?

Я имею в виду, вы были вынуждены выбрать другой язык из-за этого?

Мы исследуем использование Python для нескольких более крупных проектов, и мне кажется, что в большинстве случаев Python достаточно быстр для большинства сценариев (по сравнению, скажем, с Java), потому что он опирается на оптимизированные подпрограммы на Си.

Я хотел посмотреть, есть ли у людей случаи, когда они начинали на Python, , но в конечном итоге пришлось пойти на что-то другое из-за производительности.

Спасибо.

Ответы [ 19 ]

33 голосов
/ 22 декабря 2008

Да, у меня есть. Я написал программу для подсчета строк для двоичного (с префиксом по длине, а не с разделителем) выходного файла bcp один раз, и в итоге мне пришлось переделывать его в C, потому что Python был слишком медленным. Эта программа была довольно маленькой (потребовалось всего несколько дней, чтобы переписать ее на C), поэтому я не стал пытаться создать гибридное приложение (python glue с центральными подпрограммами, написанными на C), но это также был жизнеспособным маршрутом.

Более крупное приложение с критическими битами производительности может быть написано на комбинации C и языка более высокого уровня. Вы можете написать критические для производительности части на C с интерфейсом для Python для остальной части системы. SWIG , Pyrex или Boost.Python (если вы используете C ++) - все это обеспечивает хорошие механизмы для выполнения слежения за интерфейсом Python. API C для python более сложен, чем для Tcl или Lua , но его невозможно построить вручную. В качестве примера API-интерфейса Python / C, созданного вручную, посмотрите cx_Oracle .

Этот подход использовался во многих успешных приложениях, начиная с 1970-х годов (о которых я знаю). Mozilla была написана в основном на Javascript вокруг ядра, написанного на C. Несколько CAD-пакетов , Interleaf (система публикации технических документов) и, конечно, EMACS в основном написаны на LISP с центральным C, ассемблером или другим ядром. Довольно много коммерческих приложений с открытым исходным кодом (например, Chandler или Sungard Front Arena ) используют встроенные интерпретаторы Python и реализуют существенные части приложения на Python.

РЕДАКТИРОВАТЬ: В ответ на комментарий Dutch Masters сохранение кого-то с навыками программирования C или C ++ в команде для проекта Python дает вам возможность написать некоторые приложения для скорости. Области, в которых можно ожидать значительного прироста производительности, - это то, где приложение выполняет итеративные действия с большой структурой данных или большим объемом данных. В случае счетчика строк, приведенного выше, он должен был вдохнуть ряд файлов общим объемом в несколько гигабайт и пройти через процесс, где он считывал префикс переменной длины и использовал его для определения длины поля данных. Большинство полей были короткими (всего несколько байтов). Это было несколько неожиданно, очень низкий уровень и итеративный, что делало его естественным для C.

Многие из библиотек Python, такие как numpy , cElementTree или cStringIO , используют оптимизированное ядро ​​C с API-интерфейсом Python, который облегчает работу с данными в агрегат. Например, numpy имеет матричные структуры данных и операции, написанные на C, которые выполняют всю тяжелую работу, и Python API, который предоставляет сервисы на агрегированном уровне.

18 голосов
/ 22 декабря 2008

Это гораздо более сложный вопрос, чем люди готовы признать.

Например, может случиться так, что я могу написать программу, которая работает лучше на Python, чем на C. Ошибочный вывод из этого утверждения: «Python поэтому быстрее, чем C». В действительности, это может быть потому, что у меня гораздо более недавний опыт работы с Python и его лучшими практиками и стандартными библиотеками.

На самом деле никто не может ответить на ваш вопрос, если он не уверен, что сможет создать оптимальное решение на обоих языках, что маловероятно. Другими словами, «мое решение C было быстрее, чем мое решение Python» - это не то же самое, что «C решение быстрее, чем Python»

Готов поспорить, что Гвидо Ван Россум мог бы написать Python-решения для проблем Адама и Дастина, которые показали себя неплохо.

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

14 голосов
/ 26 января 2009

Добавление моих $ 0,02 к записи.

Моя работа заключается в разработке числовых моделей, в которых используется более 100 гигабайт данных. Сложные проблемы заключаются в том, чтобы быстро найти решение, приносящее доход (то есть время выхода на рынок). Чтобы быть коммерчески успешным, решение также должно быстро выполнить (вычислить решение за минимальное количество времени).

Для нас Python оказался отличным выбором для разработки решений по общепринятым причинам: быстрое время разработки, выразительность языка, богатые библиотеки и т. Д. Но для удовлетворения потребностей в скорости выполнения мы приняли «гибридный» подход что несколько ответов уже упоминалось.

  1. Использование NumPy для сложных в вычислительном отношении частей. Мы получаем от 1,1x до 2,5x скорость «нативного» решения C ++ с большим количеством кода, меньшим количеством ошибок и более коротким временем разработки.
  2. Pickling (сериализация объектов Python) промежуточные результаты для минимизации повторных вычислений. Природа нашей системы требует многократных шагов над одними и теми же данными, поэтому мы «запоминаем» результаты и повторно используем их, где это возможно.
  3. Профилирование и выбор лучших алгоритмов. Это было сказано в других ответах, но я повторю это: мы извлекаем cProfile и пытаемся заменить горячие точки лучшим алгоритмом. Не применимо во всех случаях.
  4. Переход на C ++. Если вышеописанное не помогает, мы вызываем библиотеку C ++. Мы используем PyBindGen для написания наших оболочек Python / C ++. Мы обнаружили, что он намного превосходит SWIG, SIP и Boost.Python, поскольку он производит прямой код Python C API без промежуточного уровня.

Читая этот список, вы можете подумать: «Какая большая переработка! Сначала я сделаю это в [C / C ++ / Java / ассемблер] и покончу с этим».

Позвольте мне представить это в перспективе. Используя Python, мы смогли за 5 недель создать работающее приложение, приносящее доход, для которого на других языках ранее требовалось 3 месяца для проектов аналогичного масштаба. Это включает время, необходимое для оптимизации частей Python, которые мы обнаружили медленными.

7 голосов
/ 22 декабря 2008

В то время как в университете мы писали систему компьютерного зрения для анализа поведения человека на основе видеоклипов. Мы использовали python из-за превосходного PIL, чтобы ускорить разработку и дать нам легкий доступ к кадрам изображения, которые мы извлекли из видео для преобразования в массивы и т. Д.

Для 90% того, что мы хотели, это было хорошо, а поскольку изображения имели достаточно низкое разрешение, скорость была неплохой. Тем не менее, некоторые процессы требовали некоторых сложных попиксельных вычислений, а также сверток, которые, как известно, медленные. Для этих конкретных областей мы переписали самые внутренние части циклов в C и просто обновили старые функции Python для вызова функций C.

Это дало нам лучшее из обоих миров. У нас была простота доступа к данным, которую предоставляет python, что позволило быстро развиваться, а затем прямолинейная скорость C для самых интенсивных вычислений.

7 голосов
/ 22 декабря 2008

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

Если что-то недостаточно быстро, мы профилируем это с помощью cProfile и находим узкие места. Обычно есть одна или две функции, которые занимают 80 или 90% времени выполнения. Затем мы берем эти функции и переписываем их в C, то, что Python упрощает с помощью своего C API. Во многих случаях это приводит к ускорению на порядок или более. Проблема исчезла. Затем мы продолжаем наш веселый путь, продолжая писать все остальное на Python. Промыть и повторить ...

Для целых модулей или классов, которые мы обычно используем Boost.python, это может быть немного сложным, но в конечном итоге работает хорошо. Если это просто функция или две, мы иногда добавляем в нее scipy.weave, если проект уже использует scipy.

5 голосов
/ 22 декабря 2008

Всякий раз, когда я нахожу узкое место Python, я переписываю этот код на C как модуль Python.

Например, у меня есть оборудование, которое отправляет пиксели изображения в виде 4-байтового 0RGB. Преобразование 8M из 0RGB в RGB в Python занимает слишком много времени, поэтому я переписал его как модуль Python.

Написание Python (или других языков более высокого уровня) намного быстрее, чем на C, поэтому я использую Python, пока не смогу.

4 голосов
/ 24 декабря 2008

Подобные вопросы могут привести к религиозной войне среди языковых людей, поэтому позвольте мне ответить на них немного по-другому.

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

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

Это длинный ответ, чтобы ответить на ваш вопрос напрямую; нет, python (иногда с расширениями C) был достаточно быстрым для всего, что мне нужно. Единственный раз, когда я действительно углубляюсь в C, это получить доступ к вещам, которые не имеют привязок Python.

Edit: Мой опыт работы программистом на Python в крупном .com, где мы используем python для всего, начиная с внешнего интерфейса наших веб-сайтов и заканчивая всеми бэк-офисными системами. Python - это язык корпоративного уровня.

4 голосов
/ 23 марта 2009

При реализации специализированного сервера memcache для определенного типа данных бэкэнд хранилища был бы более эффективным в использовании памяти, а время поиска могло бы быть уменьшено с помощью побитовых операций поиска (, то есть: O (1) просмотров ).

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

Учитывая такие инструменты, как Pyrex , реализация расширений C для Python является тривиальной задачей для любого разработчика, немного знакомого с C. Я переписал серверную часть хранения на основе Radix Tree в C и сделал его модулем Python с Pyrex в течение дня. Использование памяти для префиксов 475 КБ сократилось с 90 МБ до 8 МБ. Мы получили скачок производительности на 1200%.

Сегодня это приложение работает с pyevent (интерфейс Python для libevent) , а новый внутренний сервер хранения обрабатывает 8000 запросов в секунду на скромном одноядерном сервере, работающем как однопроцессный демон (благодаря libevent) , потребляющий менее 40 МБ памяти (включая интерпретатор Python) при обработке более 300 одновременных подключений.

Это проект, разработанный и реализованный с качеством продукции менее чем за 5 дней. Без Python и Pyrex это заняло бы больше времени.

Мы могли бы решить проблему с производительностью, просто используя более мощные серверы и переключившись на модель с несколькими процессами / несколькими экземплярами, усложняя код и задачи администрирования, сопровождаемые гораздо большим объемом памяти.

Я думаю, что вы на правильном пути, чтобы пойти с Python.

2 голосов
/ 26 июня 2010

Да, дважды:

  • Аудио DSP-приложение, которое я полностью переписал на C ++, потому что я не мог получить надлежащую производительность на Python; Я не считаю, что реализация Python потрачена впустую, потому что она позволила мне очень легко создать прототип концепции, и порт C ++ прошел гладко, потому что у меня была рабочая справочная реализация.

  • Проект процедурного графического рендеринга, где создание больших 2D текстурных карт в Python занимало много времени; Я написал C ++ DLL и использовал ctypes / windll, чтобы использовать ее из Python.

2 голосов
/ 22 декабря 2008

Вы всегда можете написать части своего приложения на Python. Не каждый компонент одинаково важен для производительности. Python легко интегрируется с C ++ изначально, с Java через Jython или с .NET через IronPython.

Кстати, IronPython более эффективен, чем реализация Python на C в некоторых тестах.

...