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

Python 提高numpy三角函数运算性能,python,performance,numpy,trigonometry,Python,Performance,Numpy,Trigonometry,我有一个相当大的代码,我需要优化。在使用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.

我有一个相当大的代码,我需要优化。在使用
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
,我几乎没有什么想法了

通过使用,可以减少触发次数。函数调用。在下面的示例中,
func1
func2
计算相同的值,但
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

你有没有试过使用像Numba、Cython、Pythran这样的Python加速器

我和皮瑟伦做了一些测试。结果如下:

原始代码:

  • 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

“所有变量都可以随机定义为…”是您感兴趣的实际用例,还是您使用
np.random.uniform
只是为了获得stackoverflow问题的一些数据?这是在循环中发生的吗?它能被转换成矩阵格式并矢量化吗?@WarrenWeckesser后者。实际数据来自于我相当大的代码中缺失的部分。@njuffa显然不是:太糟糕了,大多数现代计算环境都提供了这个功能。您可能需要考虑将输入添加到现有的<代码> NoMPy < /COD>特征请求。我不熟悉<代码> Pythran >代码>,我不知道代码< SIMD < /COD>代表什么。你能提供更多的细节吗?SIMD的意思是:单指令多数据。在现代建筑中,同时处理多个值(这里是这些数组的多个单元格)是一个概念。现代cpu处理avx(或avx2),它可以一行处理4个单元。关于Pythran,它是一个优化C++代码的Python编译器。它只处理Python代码的约束(静态类型代码和其他一些约束),但它在科学内核上工作(并专注于科学内核),像
numexpr
这样简单的东西可以让您获得与Pythran+SIMD相同的加速比。