Почему Программы Python часто медленнее, чем Эквивалентная Программа, Записанная в C или C++?

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

55
задан John Saunders 19 June 2010 в 06:07
поделиться

8 ответов

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

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

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

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

70
ответ дан 26 November 2019 в 17:43
поделиться

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

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

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

16
ответ дан 26 November 2019 в 17:43
поделиться

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

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

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

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

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

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

41
ответ дан 26 November 2019 в 17:43
поделиться

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

9
ответ дан 26 November 2019 в 17:43
поделиться

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

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

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

3
ответ дан 26 November 2019 в 17:43
поделиться

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

1
ответ дан 26 November 2019 в 17:43
поделиться

Сравнение C/C++ с Python не является справедливым сравнением. Например, сравнение гоночного автомобиля Формулы-1 с грузовиком.

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

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

4
ответ дан 26 November 2019 в 17:43
поделиться

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

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

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

4
ответ дан 26 November 2019 в 17:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: