Эквивалентность Python встроенным функциям или макросам
Я только что понял, что делаю
x.real*x.real+x.imag*x.imag
- это в три раза быстрее, чем делать
abs(x)**2
где X-массив NumPy комплексных чисел. Для удобства чтения кода я мог бы определить такую функцию, как
def abs2(x):
return x.real*x.real+x.imag*x.imag
который по-прежнему намного быстрее, чем abs(x)**2, но это за счет вызова функции. Можно ли встроить такую функцию, как я сделал бы в C, используя макрос или используя встроенное ключевое слово?
5 ответов
можно ли встроить такую функцию, как я сделал бы в C, используя макрос или используя встроенное ключевое слово?
нет. До достижения этой конкретной инструкции интерпретаторы Python даже не знают, есть ли такая функция, а тем более, что она делает.
Как отмечено в комментариях, PyPy будет встроен автоматически (вышеизложенное все еще выполняется - он" просто " генерирует оптимизированную версию во время выполнения, извлекает из нее выгоду, но выходит из нее, когда invalidated), хотя в этом конкретном случае это не помогает, поскольку реализация NumPy на PyPy началась только недавно и даже не является бета-уровнем по сей день. Но суть в следующем: Не беспокойтесь об оптимизации на этом уровне в Python. Либо реализации оптимизируют его сами, либо нет, это не ваша ответственность.
не совсем то, что просил OP, но близко:
Inliner inlines вызовы функций Python. Доказательство концепции для этот блог пост
from inliner import inline @inline def add_stuff(x, y): return x + y def add_lots_of_numbers(): results = [] for i in xrange(10): results.append(add_stuff(i, i+1))
в приведенном выше коде функция add_lots_of_numbers преобразуется в это:
def add_lots_of_numbers(): results = [] for i in xrange(10): results.append(i + i + 1)
также любой, кто интересуется этим вопросом и осложнениями, связанными с реализацией такого оптимизатора в CPython, также может захотеть взглянуть at:
Я согласен со всеми остальными, что такие оптимизации просто причинят вам боль на CPython, что если вы заботитесь о производительности, вы должны рассмотреть PyPy (хотя наш NumPy может быть слишком неполным, чтобы быть полезным). Однако я не соглашусь и скажу, что вы можете заботиться о таких оптимизациях на PyPy, а не об этом конкретно, как было сказано, PyPy делает это автоматически, но если вы хорошо знаете PyPy, вы действительно можете настроить свой код, чтобы PyPy испускал сборку, которую вы хотите, а не то, что вам нужно почти всегда.
нет.
ближе всего к макросам C вы можете получить скрипт (awk или другой), который вы можете включить в makefile, и который заменяет определенный шаблон, такой как abs(x)**2 в ваших скриптах python с длинной формой.
на самом деле это может быть еще быстрее рассчитать, например:
x.real** 2+ x.imag** 2
таким образом, дополнительная стоимость вызова функции, вероятно, уменьшится. Давайте посмотрим:
In []: n= 1e4
In []: x= randn(n, 1)+ 1j* rand(n, 1)
In []: %timeit x.real* x.real+ x.imag* x.imag
10000 loops, best of 3: 100 us per loop
In []: %timeit x.real** 2+ x.imag** 2
10000 loops, best of 3: 77.9 us per loop
и инкапсулирование вычисления в функцию:
In []: def abs2(x):
..: return x.real** 2+ x.imag** 2
..:
In []: %timeit abs2(x)
10000 loops, best of 3: 80.1 us per loop
В любом случае (как указывали другие) Этот вид микро-оптимизации (чтобы избежать вызова функции) не является действительно продуктивным способом написания кода python.