Ove*_*gon 6 python performance for-loop numpy python-3.x
N, M = 1000, 4000000
a = np.random.uniform(0, 1, (N, M))
k = np.random.randint(0, N, (N, M))
out = np.zeros((N, M))
for i in range(N):
for j in range(M):
out[k[i, j], j] += a[i, j]
Run Code Online (Sandbox Code Playgroud)
我使用很长的 for 循环;%%timeit在上面pass替换操作产量
1min 19s ± 663 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Run Code Online (Sandbox Code Playgroud)
这在上下文中是不可接受的(C++ 耗时 6.5 秒)。没有理由使用 Python 对象完成上述操作;数组具有明确定义的类型。在 C/C++ 中实现它作为扩展对开发人员和用户端来说都是一种矫枉过正;我只是将数组传递给循环并进行算术运算。
有没有办法告诉 Numpy“将此逻辑移至 C”,或其他可以处理仅涉及数组的嵌套循环的库?我在一般情况下寻求它,而不是针对这个特定示例的解决方法(但如果你有一个,我可以打开一个单独的问答)。
这基本上是Numba背后的想法。不如 C 快,但可以接近……它使用 jit 编译器将 python 代码编译为机器,并且与大多数 Numpy 函数兼容。(在文档中您可以找到所有详细信息)
import numpy as np
from numba import njit
@njit
def f(N, M):
a = np.random.uniform(0, 1, (N, M))
k = np.random.randint(0, N, (N, M))
out = np.zeros((N, M))
for i in range(N):
for j in range(M):
out[k[i, j], j] += a[i, j]
return out
def f_python(N, M):
a = np.random.uniform(0, 1, (N, M))
k = np.random.randint(0, N, (N, M))
out = np.zeros((N, M))
for i in range(N):
for j in range(M):
out[k[i, j], j] += a[i, j]
return out
Run Code Online (Sandbox Code Playgroud)
纯Python:
%%timeit
N, M = 100, 4000
f_python(M, N)
Run Code Online (Sandbox Code Playgroud)
每个循环 338 ms ± 12.6 ms(7 次运行的平均值 ± 标准偏差,每次 1 次循环)
使用 Numba:
%%timeit
N, M = 100, 4000
f(M, N)
Run Code Online (Sandbox Code Playgroud)
每个循环 12 ms ± 534 µs(7 次运行的平均值 ± 标准偏差,每次 100 次循环)
| 归档时间: |
|
| 查看次数: |
133 次 |
| 最近记录: |