提高 numpy 三角函数运算的性能

Improve performance of operation on numpy trigonometric functions

我有一个相当大的代码需要优化。在使用 time.time() 进行一些分析后,我发现占用处理时间最多的行(执行了数千次)是这一行:

A = np.cos(a) * np.cos(b) - np.sin(a) * np.sin(b) * np.sin(c - d)

其中所有变量都可以随机定义:

N = 5000
a = np.random.uniform(0., 10., N)
b = np.random.uniform(0., 50., N)
c = np.random.uniform(0., 30., N)
d = np.random.uniform(0., 25., N)

有没有办法提高A的计算性能?因为我已经在使用 numpy,所以我几乎没有想法。

通过使用product-to-sum trig. identities,可以减少触发次数。函数调用。在下文中,func1func2 计算相同的值,但 func2 对 trig 的调用较少。函数。

import numpy as np

def func1(a, b, c, d):
    A = np.cos(a) * np.cos(b) - np.sin(a) * np.sin(b) * np.sin(c - d)
    return A

def func2(a, b, c, d):
    s = np.sin(c - d)
    A = 0.5*((1 - s)*np.cos(a - b) + (1 + s)*np.cos(a + b))
    return A

这是与N = 5000的时间比较:

In [48]: %timeit func1(a, b, c, d)
1000 loops, best of 3: 374 µs per loop

In [49]: %timeit func2(a, b, c, d)
1000 loops, best of 3: 241 µs per loop

您是否尝试过使用 Python 加速器,例如 Numba、Cython、Pythran 或其他任何东西?

我用 Pythran 做了一些测试。这是结果:

原代码:

  • Python + numpy:1000 次循环,最好的 3 次:每次循环 1.43 毫秒
  • Pythran:1000 次循环,每次循环 3:777usec 中最好的
  • Pythran + SIMD:1000 个循环,最好的 3:488 每个循环 usec

沃伦提供的代码:

  • Python + numpy:1000 次循环,最好的 3 次:每次循环 1.05 毫秒
  • Pythran:1000 个循环,最好的 3 个:每个循环 646 usec
  • Pythran + SIMD:1000 个循环,最好的 3 个:每个循环 425 usec

这是用 N = 5000 完成的

  • 更新 * :

这是代码:

# pythran export func1(float[], float[], float[], float[])
# pythran export func2(float[], float[], float[], float[])
import numpy as np

def func1(a, b, c, d):
    A = np.cos(a) * np.cos(b) - np.sin(a) * np.sin(b) * np.sin(c - d)
    return A

def func2(a, b, c, d):
    s = np.sin(c - d)
    A = 0.5*((1 - s)*np.cos(a - b) + (1 + s)*np.cos(a + b))
    return A

和命令行:

$ pythran test.py  # Default compilation
$ pythran test.py -march=native -DUSE_BOOST_SIMD  # Pythran with code vectorization