numpy数组计算比等效的Java代码慢

Mic*_*hal 0 python arrays performance numpy

我正在尝试使用Python处理大型2D数组,但速度非常慢。例如:

start = time.time()
result = numpy.empty([5000, 5000])

for i in range(5000):
    for j in range(5000):
        result[i, j] = (i * j) % 10

end = time.time()
print(end - start) # 8.8 s
Run Code Online (Sandbox Code Playgroud)

Java中的相同程序要快得多:

long start = System.currentTimeMillis();
int[][] result = new int[5000][5000];

for (int i = 0; i < 5000; i++) {
    for (int j = 0; j < 5000; j++) {
        result[i][j] = (i * j) % 10;
    }
}

long end = System.currentTimeMillis();
System.out.println(end - start); // 121 ms
Run Code Online (Sandbox Code Playgroud)

这是因为Python是解释语言吗?有什么办法可以改善吗?还是为什么Python在处理矩阵,人工智能等方面如此受欢迎?

use*_*ica 6

您实际上并没有使用 NumPy的功能-您是在Python级别手动执行循环。这大致类似于想知道为什么当您将汽车拖到自己身后时,如果花这么长时间才能步行到商店,那么每个人都使用汽车。

使用本机NumPy操作将您的工作推入C级循环。例如,

temp = numpy.arange(5000)
result = numpy.outer(temp, temp) % 10
# or result = temp * temp[:, None] % 10
Run Code Online (Sandbox Code Playgroud)

这样会更快。


NPE*_*NPE 6

阅读最后,了解NumPy如何比Java代码好5倍。

numpy向量计算的优势在于它。您的Python代码依赖于解释循环,而迭代循环往往很慢。

我将您的Python代码重写为矢量化计算,并立即将其加速了约16倍:

In [41]: v = np.arange(5000)

In [42]: %timeit np.outer(v, v) % 10
1 loop, best of 3: 544 ms per loop
Run Code Online (Sandbox Code Playgroud)

% 10就地计算而不是创建新的阵列可将速度提高20%:

In [37]: def f(n):
    ...:     v = np.arange(n)
    ...:     a = np.outer(v, v)
    ...:     a %= 10
    ...:     return a
    ...:

In [39]: %timeit f(5000)
1 loop, best of 3: 437 ms per loop
Run Code Online (Sandbox Code Playgroud)

编辑1:用32位而不是64位进行计算(以匹配Java代码)基本上与Java的性能匹配— h / t到@ user2357112指出了这一点:

In [50]: def f(n):
    ...:  v = np.arange(n, dtype=np.int32)
    ...:  a = np.outer(v, v)
    ...:  a %= 10
    ...:  return a
    ...:

In [51]: %timeit f(5000)
10 loops, best of 3: 126 ms per loop
Run Code Online (Sandbox Code Playgroud)

编辑2:通过一点点工作,我们可以使这段代码比Java实现快5倍左右(此处ne指的是numexpr模块):

In [69]: v = np.arange(5000, dtype=np.int32)

In [70]: vt = v[np.newaxis].T

In [71]: %timeit ne.evaluate('v * vt % 10')
10 loops, best of 3: 25.3 ms per loop
Run Code Online (Sandbox Code Playgroud)

编辑3:请确保还看看@ max9111给出答案

  • 指定`dtype ='int32'`并查看会发生什么-除非您使用Windows,否则可能会执行等效于Java`long`的计算。这可以解决时序差异的另一部分。 (3认同)