Почему программы на Python часто работают медленнее, чем эквивалентные программы, написанные на C или C ++? - PullRequest
51 голосов
/ 13 июня 2010

Почему Python в среднем медленнее, чем C / C ++? Я выучил Python как свой первый язык программирования, но я только начал с C и уже чувствую, что вижу четкую разницу.

Ответы [ 8 ]

66 голосов
/ 13 июня 2010

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

Это правда, что код C обычно работает в 10-100 раз быстрее, чем код Python, если вы измеряете только время выполнения.Однако, если вы также включите время разработки, Python часто обгоняет C. Для многих проектов время разработки гораздо более критично, чем производительность времени выполнения.Более длительное время разработки напрямую приводит к дополнительным затратам, меньшему количеству функций и более медленному выходу на рынок.

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

Другие интерпретируемые языки, такие как байт-код Java и байт-код .NET, работают быстрее, чем Python, потому что стандартные дистрибутивы включают JIT-компилятор , который компилирует байт-код в собственный код во время выполнения.Причина, по которой CPython не имеет JIT-компилятора, заключается в том, что динамическая природа Python затрудняет его написание. работа в progress , чтобы написать более быструю среду исполнения Python, так что вы должны ожидать, что в будущем разрыв в производительности уменьшится, но, вероятно, пройдет некоторое время, прежде чем стандартный дистрибутив Python включаетмощный JIT-компилятор.

39 голосов

CPython особенно медленный, потому что у него нет оптимизатора Just in Time (поскольку он является эталонной реализацией и в некоторых случаях выбирает простоту над производительностью). Unladen Swallow - это проект по добавлению JIT с поддержкой LLVM в CPython, обеспечивающий значительное ускорение. Вполне возможно, что Jython и IronPython намного быстрее, чем CPython, а также поддерживаются сильно оптимизированными виртуальными машинами (JVM и .NET CLR).

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

Например, вызов f для объекта A вызовет возможные поиски в __dict__, вызовы __getattr__ и т. Д., А затем, наконец, вызовет __call__ для вызываемого объекта f.

Что касается динамической типизации, существует множество оптимизаций, которые можно выполнить, если вы знаете, с каким типом данных вы имеете дело. Например, в Java или C, если у вас есть прямой массив целых чисел, которые вы хотите суммировать, код окончательной сборки может быть таким же простым, как получение значения по индексу i, добавление его к accumulator, а затем увеличение i.

В Python очень сложно сделать код таким оптимальным. Скажем, у вас есть объект подкласса списка, содержащий int s. Прежде чем добавить что-либо, Python должен вызвать list.__getitem__(i), затем добавить это к «аккумулятору», вызвав accumulator.__add__(n), а затем повторить. Здесь может произойти множество альтернативных поисков, потому что другой поток мог изменить, например, метод __getitem__, диктат экземпляра списка или диктат класса, между вызовами add или getitem. Даже поиск аккумулятора и списка (и любой переменной, которую вы используете) в локальном пространстве имен вызывает поиск по умолчанию. Эти же накладные расходы применяются при использовании любого определенного пользователем объекта, хотя для некоторых встроенных типов он несколько смягчается.

Стоит также отметить, что примитивные типы, такие как bigint (int в Python 3, long в Python 2.x), list, set, dict и т. Д. И т. Д., - это то, что люди часто используют в Python. Существует множество встроенных операций на этих объектах, которые уже достаточно оптимизированы. Например, для приведенного выше примера вы просто позвоните sum(list) вместо использования аккумулятора и индекса. Придерживаясь этого, и немного разбирая числа с помощью int / float / complex, у вас, как правило, не будет проблем со скоростью, и если вы это сделаете, то, вероятно, есть небольшая критическая по времени единица (например, функция дайджеста SHA2), которую вы можете просто перейдите на C (или Java-код в Jython). Дело в том, что когда вы кодируете C или C ++, вы тратите лотов времени на то, что вы можете сделать за несколько секунд / строк кода Python. Я бы сказал, что компромисс всегда стоит, за исключением случаев, когда вы занимаетесь чем-то вроде встроенного программирования или программирования в реальном времени и не можете себе этого позволить.

11 голосов
/ 13 июня 2010

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

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

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

9 голосов
/ 13 июня 2010

Разница между python и C - это обычная разница между интерпретируемым (байт-кодом) и скомпилированным (на родном) языке.Лично я не вижу Python медленным, он прекрасно справляется.Если вы попытаетесь использовать его за пределами его сферы, конечно, это будет медленнее.Но для этого вы можете написать C-расширения для Python, который помещает критичные по времени алгоритмы в собственный код, ускоряя его.

4 голосов
/ 25 июня 2010

Python обычно реализуется как язык сценариев.Это означает, что он проходит через интерпретатор, что означает, что он переводит код на лету на машинный язык, а не имеет исполняемый файл полностью на машинном языке с самого начала.В результате он должен оплатить стоимость перевода кода в дополнение к его выполнению.Это верно даже для CPython, даже если он компилируется в байт-код, который ближе к машинному языку и поэтому может быть переведен быстрее.В состав Python также входят некоторые очень полезные функции времени выполнения, такие как динамическая типизация, но такие вещи, как правило, не могут быть реализованы даже в самых эффективных реализациях без больших затрат времени выполнения.Python нередко бывает где-то в 200 раз медленнее, чем C ++.Если вы используете CPython, это время можно сократить вдвое, но оно еще далеко не так быстро.Со всеми этими вкусностями Рунтми приходит цена.Есть много тестов, чтобы показать это, и , вот особенно хороший.Как признается на первой странице, критерии являются ошибочными.Все они представлены пользователями, которые стараются изо всех сил написать эффективный код на языке по своему выбору, но это дает вам хорошее общее представление.

Я рекомендую вам попробовать смешать их вместе, если вы беспокоитесь об эффективности:тогда вы сможете получить лучшее из обоих миров.Я в основном программист на C ++, но я думаю, что многие люди склонны слишком много кодировать мирского высокоуровневого кода на C ++, когда это просто неприятно (время компиляции - только один пример).Сочетание языка сценариев с эффективным языком, таким как C / C ++, который ближе к металлу, - это действительно способ сбалансировать эффективность (производительность) программиста с эффективностью обработки.

3 голосов
/ 13 июня 2010

Сравнение C / C ++ с Python не является честным сравнением.Как сравнивать гоночный автомобиль F1 с грузовиком.

Что удивительно, так это то, насколько быстрый Python по сравнению с аналогами других динамических языков.В то время как методология часто считается ошибочной, посмотрите на The Computer Language Benchmark Game , чтобы увидеть относительную скорость языка в аналогичных алгоритмах.

Сравнение с Perl, Ruby и C # более «справедливо»

3 голосов
/ 13 июня 2010

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

RPython , кажется, способОбойти проблему оптимизации.

Тем не менее, она, вероятно, не будет соответствовать производительности C для перебора чисел и тому подобного.

1 голос
/ 13 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...