Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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__, dict экземпляра списка или dict класса, между вызовами add или getitem. Даже поиск аккумулятора и списка (и любой переменной, которую вы используете) в локальном пространстве имен вызывает поиск в dict. Эти же накладные расходы применяются при использовании любого пользовательского объекта, хотя для некоторых встроенных типов он несколько смягчается.

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

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

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

Ответ 6

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

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

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

Ответ 7

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

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

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

Ответ 8

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