Эквивалентность 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.