Python Numpy数组计算速度比等效Java代码慢

Python Numpy数组计算速度比等效Java代码慢,python,arrays,performance,numpy,Python,Arrays,Performance,Numpy,我试图用Python处理大型2D数组,但速度非常慢。例如: 开始=时间 结果=numpy.empty[50005000] 对于5000范围内的i: 对于5000范围内的j: 结果[i,j]=i*j%10 结束=时间 打印结束-开始8.8秒 Java中的相同程序要快得多: 长启动=System.currentTimeMillis; int[][]结果=新int[5000][5000]; 对于int i=0;i

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

开始=时间 结果=numpy.empty[50005000] 对于5000范围内的i: 对于5000范围内的j: 结果[i,j]=i*j%10 结束=时间 打印结束-开始8.8秒 Java中的相同程序要快得多:

长启动=System.currentTimeMillis; int[][]结果=新int[5000][5000]; 对于int i=0;i<5000;i++{ 对于int j=0;j<5000;j++{ 结果[i][j]=i*j%10; } } 长端=System.currentTimeMillis; System.out.printlend-开始;//121毫秒
这是因为Python是解释语言?有什么办法可以改进吗?或者为什么Python在处理矩阵、人工智能等方面如此流行?

Python在AI方面非常流行,原因有很多: -易于原型化 -很多ML库/大commu -以CUDA为例,使用gpu对张量进行大规模并行计算

对于我们的问题,请尝试在python上使用本机列表如果您使用的是numpy,它可能会更重

您实际上没有使用numpy的功能-您正在python级别手动执行循环。这大致相当于想知道,当你把车拖在身后时,如果步行到商店要花很长时间,为什么每个人都要用汽车

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

temp = numpy.arange(5000)
result = numpy.outer(temp, temp) % 10
# or result = temp * temp[:, None] % 10
这会快得多。

读到最后,看看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
就地计算%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
编辑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
编辑2:通过一点工作,我们可以使这段代码比您的Java实现快5倍

编辑3:请务必同时查看。

有什么方法可以改进它吗

请参见时间性能差异:

In [13]: arr = np.empty([5000, 5000])                                                                          

In [14]: %timeit np.multiply(*np.indices(arr.shape)) % 10                                                      
482 ms ± 2.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
其中表示网格的索引

为什么Python在处理矩阵、人工智能等方面如此流行

Numpy例程是用C语言实现的,C语言即使不是最快的语言,也是最快的语言之一,并且使用密集的数组。相关主题:


您还可以暗示,一个流行且功能强大的数据分析/数据科学库。由于其灵活的数据表示、简洁的语法、广泛的功能集和高效处理大型数据集,许多专家都首选和选择它。

已经展示的@user2357112和@NPE示例的另一个选择是使用Jit编译器。纯解释的Python循环非常慢,应该避免在性能重要的地方使用

范例

时间安排


指定dtype='int32'并查看会发生什么-除非您在Windows上,否则您可能正在使用Java long的等效语言进行计算。这可能是造成时间差的另一个原因。@user2357112:你说得对,谢谢!让我更新答案。
In [13]: arr = np.empty([5000, 5000])                                                                          

In [14]: %timeit np.multiply(*np.indices(arr.shape)) % 10                                                      
482 ms ± 2.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
import numpy as np
import numba as nb
import numexpr as ne

@nb.njit(parallel=True)
def func_1(num):
    result = np.empty((num, num),dtype=np.int32)
    for i in nb.prange(result.shape[0]):
        for j in range(result.shape[1]):
            result[i, j] = (i * j) % 10
    return result
#The first call has a higher overhead due to compilation
#parallel: @nb.njit(parallel=True)
%timeit res=func_1(5000)
#20.7 ms ± 1.11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#single threaded: @nb.njit(parallel=True)
%timeit res=func_1(5000)
#71.9 ms ± 521 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

#NPE
%%timeit
v = np.arange(5000, dtype=np.int32)
vt = v[np.newaxis].T
ne.evaluate('v * vt % 10')
#35.5 ms ± 863 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)