Python pycuda';s gpuarray.dot()函数?

Python pycuda';s gpuarray.dot()函数?,python,numpy,pycuda,Python,Numpy,Pycuda,Pycuda的gpuarray.dot()操作与numpy.dot()操作的作用不同。这是故意的吗 例如,下面的代码先执行numpy.dot(),然后执行gpuarray.dot()。前者返回5x5数组,后者返回单个数字 import numpy as np import pycuda.autoinit import pycuda.gpuarray as gpuarray np.random.seed(1) print ("\nNUMPY: result of np.dot - OK") a

Pycuda的gpuarray.dot()操作与numpy.dot()操作的作用不同。这是故意的吗

例如,下面的代码先执行numpy.dot(),然后执行gpuarray.dot()。前者返回5x5数组,后者返回单个数字

import numpy as np
import pycuda.autoinit
import pycuda.gpuarray as gpuarray
np.random.seed(1)

print ("\nNUMPY: result of np.dot - OK")
a = np.array(2 * np.random.random((5, 5)) - 1)
b = np.array(2 * np.random.random((5, 5)) - 1)
a_b_dot = np.dot(a, b)
print (type(a_b_dot), a_b_dot.shape)
print (a_b_dot)

print ("\nPYCUDA: result of gpuarray.dot - NOT OK")
a_gpu = gpuarray.to_gpu(a)
b_gpu = gpuarray.to_gpu(b)
a_b_dot = gpuarray.dot(a_gpu, b_gpu)
print (type(a_b_dot), a_b_dot.shape)
print (a_b_dot)

输出为:

NUMPY: result of np.dot - OK
<class 'numpy.ndarray'> (5, 5)
[[-0.4289689  -1.07826831  0.35264673  1.17316284  0.37989478]
 [-0.23539466  0.62140658  0.02890465  0.64194572 -0.90554719]
 [ 0.6308665  -0.5418927   0.15072667  1.53949101 -0.17648109]
 [-0.28165967 -1.06345895  0.17784186 -0.50902276  1.27061422]
 [ 0.15769648  0.01993701 -0.42621895 -0.07254009 -0.23463897]]

PYCUDA: result of gpuarray.dot - NOT OK
<class 'pycuda.gpuarray.GPUArray'> ()
-0.3611777016515303
NUMPY:np.dot的结果-正常
(5, 5)
[[-0.4289689  -1.07826831  0.35264673  1.17316284  0.37989478]
[-0.23539466  0.62140658  0.02890465  0.64194572 -0.90554719]
[ 0.6308665  -0.5418927   0.15072667  1.53949101 -0.17648109]
[-0.28165967 -1.06345895  0.17784186 -0.50902276  1.27061422]
[ 0.15769648  0.01993701 -0.42621895 -0.07254009 -0.23463897]]
PYCUDA:gpuarray.dot的结果-不正常
()
-0.3611777016515303

我很确定pycuda这样做的原因是因为它需要pycuda依赖于cusparse/cublas(因此它不必重新实现这些东西)。扩展这一功能的最简单方法是将点积应用到整个功能中,如果最终用户需要更高级的功能,可以让他们找到自己的矩阵乘法库

如果你真的想用这种方法在矩阵上做点积,你只需要使用矩阵乘法,请看下面的例子来证明:

import numpy as np

print("\nNUMPY: result of np.dot - OK")
a = np.array(2 * np.random.random((5, 5)) - 1)
b = np.array(2 * np.random.random((5, 5)) - 1)
a_b_dot = np.dot(a, b)
a_mul_b = np.matmul(a, b)
print(type(a_b_dot), a_b_dot.shape)
print(a_b_dot)

print(type(a_mul_b), a_mul_b.shape)
print(a_mul_b)

NUMPY: result of np.dot - OK
<class 'numpy.ndarray'> (5, 5)
[[-0.12441477 -0.28175903  0.36632673  0.35687491 -0.25773564]
 [-0.57845471 -0.4097741   0.3505651  -0.23822489  1.17375904]
 [-0.19920533 -0.43918224  0.62438656  0.6326451  -0.27798801]
 [ 0.67128494  0.44472894 -0.57700879 -0.57246653 -0.0336262 ]
 [ 0.49149948 -0.65774616  1.09320886  0.76179777 -0.76590202]]
<class 'numpy.ndarray'> (5, 5)
[[-0.12441477 -0.28175903  0.36632673  0.35687491 -0.25773564]
 [-0.57845471 -0.4097741   0.3505651  -0.23822489  1.17375904]
 [-0.19920533 -0.43918224  0.62438656  0.6326451  -0.27798801]
 [ 0.67128494  0.44472894 -0.57700879 -0.57246653 -0.0336262 ]
 [ 0.49149948 -0.65774616  1.09320886  0.76179777 -0.76590202]]

在scipy的幕后,您使用的是一个cuda dll后端,它可以将事物转换为CType之类的东西,您会注意到乘法的原语级别比numpy低很多(在大多数情况下坚持使用二维)。如果您确实需要在AND矩阵中使用乘法矩阵乘法,它们仍然是2d,但是您可以使用后端批处理函数批处理它们,或者

这个有点旧的线程说,
gpuarray.dot
只是向量点积,产生标量
np.dot
在1d数组中也可以这样做,但您正在使用它进行2d矩阵乘法。哇,这是从2012年开始的。如果今天仍然是这样,我会感到惊讶,因为我认为np.dot()是一个非常常见的操作。除非,否则答案是GPU不能更快地完成此操作,因此不需要实现它-谢谢这是真的,我在我的例子中使用了一个平方矩阵,但我需要这个非平方矩阵。
>>> import pycuda.autoinit
>>> import pycuda.gpuarray as gpuarray
>>> import numpy as np
>>> import skcuda.linalg as linalg
>>> import skcuda.misc as misc
>>> linalg.init()
>>> a = np.asarray(np.random.rand(4, 2), np.float32)
>>> b = np.asarray(np.random.rand(2, 2), np.float32)
>>> a_gpu = gpuarray.to_gpu(a)
>>> b_gpu = gpuarray.to_gpu(b)
>>> c_gpu = linalg.dot(a_gpu, b_gpu)
>>> np.allclose(np.dot(a, b), c_gpu.get())
True
>>> d = np.asarray(np.random.rand(5), np.float32)
>>> e = np.asarray(np.random.rand(5), np.float32)
>>> d_gpu = gpuarray.to_gpu(d)
>>> e_gpu = gpuarray.to_gpu(e)
>>> f = linalg.dot(d_gpu, e_gpu)
>>> np.allclose(np.dot(d, e), f)
True