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

Эквивалентность Python для встроенных функций или макросов

Я только понял, что делать

x.real*x.real+x.imag*x.imag

в три раза быстрее, чем выполнение

abs(x)**2

где x - массив с множеством чисел. Для чтения кода я мог бы определить функцию типа

def abs2(x):
    return x.real*x.real+x.imag*x.imag

который все еще намного быстрее, чем abs (x) ** 2, но он стоит за вызовом функции. Можно ли встроить такую ​​функцию, как я бы сделал в C с использованием макроса или с помощью встроенного ключевого слова?

4b9b3361

Ответ 1

Можно ли встроить такую ​​функцию, как я бы сделал в C с использованием макроса или с помощью встроенного ключевого слова?

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

Как отмечено в комментариях, PyPy будет автоматически встроен (выше все еще выполняется - он "просто" генерирует оптимизированную версию во время выполнения, извлекает выгоду из нее, но выходит из нее, когда она недействительна) хотя в этом конкретном случае это не помогает, поскольку внедрение NumPy на PyPy началось совсем недавно и даже не дошло до бета-уровня по сей день. Но суть в следующем: не беспокойтесь об оптимизации на этом уровне в Python. Либо реализация оптимизирует его самостоятельно, либо нет, это не ваша ответственность.

Ответ 2

Не совсем то, что попросил ОП, но близко:

Inliner включает вызовы функций 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, может также захотеть взглянуть на:

Ответ 3

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

Ответ 4

Нет.

Ближе всего вы можете перейти к макросам C - это script (awk или другое), которые вы можете включить в make файл, и который заменяет определенный шаблон, такой как abs (x) ** 2 в ваших сценариях python с длинным форма.

Ответ 5

На самом деле, возможно, еще быстрее вычислить, например:

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.

Ответ 6

Вы можете попробовать использовать lambda:

abs2 = lambda x : x.real*x.real+x.imag*x.imag

затем позвоните по:

y = abs2(x)