无法复制比较 Python、Numpy 和 Numba 矩阵乘法的结果
Cannot replicate results comparing Python, Numpy and Numba matrix multiplication
因此,在评估加速 Python 代码的可能性时,我遇到了这个 Stack Overflow post:
numba 的性能给我留下了深刻的印象,并在 numba 中实现了我们的一些功能。不幸的是,加速只适用于非常小的矩阵,而对于大矩阵,与之前的 scipy 稀疏实现相比,代码变得非常慢。我认为这是有道理的,但我还是在原来的post(下面的代码)中重复了测试。
当使用 1000 x 1000 矩阵时,根据 post 即使是 python 实施也应该花费大约 0.01 秒。不过,这是我的结果:
python : 769.6387 秒
numpy:0.0660 秒
数字:3.0779 秒
scipy : 0.0030 秒
我做错了什么以获得与原始结果如此不同的结果 post?我复制了这些功能,但没有改变任何东西。我尝试了 Python 3.5.1(64 位)和 Python 2.7.10(32 位),一位同事尝试了相同的代码,结果相同。这是 100x100 矩阵的结果:
python : 0.6916 秒
numpy:0.0035 秒
数字:0.0015 秒
scipy : 0.0035 秒
我是不是犯了一些明显的错误?
import numpy as np
import numba as nb
import scipy.sparse
import time
class benchmark(object):
def __init__(self, name):
self.name = name
def __enter__(self):
self.start = time.time()
def __exit__(self, ty, val, tb):
end = time.time()
print("%s : %0.4f seconds" % (self.name, end-self.start))
return False
def dot_py(A, B):
m, n = A.shape
p = B.shape[1]
C = np.zeros((m, p))
for i in range(0, m):
for j in range(0, p):
for k in range(0, n):
C[i, j] += A[i, k] * B[k, j]
return C
def dot_np(A, B):
C = np.dot(A,B)
return C
def dot_scipy(A, B):
C = A * B
return C
dot_nb = nb.jit(nb.float64[:,:](nb.float64[:,:], nb.float64[:,:]), nopython=True)(dot_py)
dim_x = 1000
dim_y = 1000
a = scipy.sparse.rand(dim_x, dim_y, density=0.01)
b = scipy.sparse.rand(dim_x, dim_y, density=0.01)
a_full = a.toarray()
b_full = b.toarray()
print("starting test")
with benchmark("python"):
dot_py(a_full, b_full)
with benchmark("numpy"):
dot_np(a_full, b_full)
with benchmark("numba"):
dot_nb(a_full, b_full)
with benchmark("scipy"):
dot_scipy(a, b)
print("finishing test")
编辑:
供以后看到此内容的任何人使用。这是我在使用稀疏 nxn 矩阵时得到的结果(1% 的元素是非零的)。
在 你从哪里得到代码的问题中,m = n = 3
和 p
是可变的,而你使用的是 m = n = 1000
,这将使时间上的巨大差异。
因此,在评估加速 Python 代码的可能性时,我遇到了这个 Stack Overflow post:
numba 的性能给我留下了深刻的印象,并在 numba 中实现了我们的一些功能。不幸的是,加速只适用于非常小的矩阵,而对于大矩阵,与之前的 scipy 稀疏实现相比,代码变得非常慢。我认为这是有道理的,但我还是在原来的post(下面的代码)中重复了测试。
当使用 1000 x 1000 矩阵时,根据 post 即使是 python 实施也应该花费大约 0.01 秒。不过,这是我的结果:
python : 769.6387 秒
numpy:0.0660 秒
数字:3.0779 秒
scipy : 0.0030 秒
我做错了什么以获得与原始结果如此不同的结果 post?我复制了这些功能,但没有改变任何东西。我尝试了 Python 3.5.1(64 位)和 Python 2.7.10(32 位),一位同事尝试了相同的代码,结果相同。这是 100x100 矩阵的结果:
python : 0.6916 秒
numpy:0.0035 秒
数字:0.0015 秒
scipy : 0.0035 秒
我是不是犯了一些明显的错误?
import numpy as np
import numba as nb
import scipy.sparse
import time
class benchmark(object):
def __init__(self, name):
self.name = name
def __enter__(self):
self.start = time.time()
def __exit__(self, ty, val, tb):
end = time.time()
print("%s : %0.4f seconds" % (self.name, end-self.start))
return False
def dot_py(A, B):
m, n = A.shape
p = B.shape[1]
C = np.zeros((m, p))
for i in range(0, m):
for j in range(0, p):
for k in range(0, n):
C[i, j] += A[i, k] * B[k, j]
return C
def dot_np(A, B):
C = np.dot(A,B)
return C
def dot_scipy(A, B):
C = A * B
return C
dot_nb = nb.jit(nb.float64[:,:](nb.float64[:,:], nb.float64[:,:]), nopython=True)(dot_py)
dim_x = 1000
dim_y = 1000
a = scipy.sparse.rand(dim_x, dim_y, density=0.01)
b = scipy.sparse.rand(dim_x, dim_y, density=0.01)
a_full = a.toarray()
b_full = b.toarray()
print("starting test")
with benchmark("python"):
dot_py(a_full, b_full)
with benchmark("numpy"):
dot_np(a_full, b_full)
with benchmark("numba"):
dot_nb(a_full, b_full)
with benchmark("scipy"):
dot_scipy(a, b)
print("finishing test")
编辑:
供以后看到此内容的任何人使用。这是我在使用稀疏 nxn 矩阵时得到的结果(1% 的元素是非零的)。
在 m = n = 3
和 p
是可变的,而你使用的是 m = n = 1000
,这将使时间上的巨大差异。