Python 为什么通过pytorch张量的循环如此缓慢(与Numpy相比)?

Python 为什么通过pytorch张量的循环如此缓慢(与Numpy相比)?,python,numpy,pytorch,tensor,Python,Numpy,Pytorch,Tensor,我最近一直在处理图像变换,遇到了这样一种情况:我有一个大数组(形状为100000 x 3),其中每一行代表3D空间中的一个点,如: pnt=[x y z] 我所要做的就是迭代每个点,然后用一个称为T(shape=3x3)的矩阵乘以每个点 使用Numpy进行测试: def变换(pnt_云,T): i=0 对于pnt_云中的pnt: xyz_pnt=np.dot(T,pnt) 如果xyz_pnt[0]>0: arr[i]=xyz_pnt[0] i+=1 返回arr 调用以下代码并计算运行时(使用

我最近一直在处理图像变换,遇到了这样一种情况:我有一个大数组(形状为100000 x 3),其中每一行代表3D空间中的一个点,如:

pnt=[x y z]
我所要做的就是迭代每个点,然后用一个称为T(shape=3x3)的矩阵乘以每个点

使用Numpy进行测试:
def变换(pnt_云,T):
i=0
对于pnt_云中的pnt:
xyz_pnt=np.dot(T,pnt)
如果xyz_pnt[0]>0:
arr[i]=xyz_pnt[0]
i+=1
返回arr
调用以下代码并计算运行时(使用%时间)将给出输出:

Out[190]: CPU times: user 670 ms, sys: 7.91 ms, total: 678 ms
Wall time: 674 ms
Out[199]: CPU times: user 6.15 s, sys: 28.1 ms, total: 6.18 s
Wall time: 6.09 s
用Pytork张量测试:
导入火炬
张量cld=火炬张量(pnt_云)
张量T=火炬。张量(T)
def变换(pnt_云,T):
深度数组=火炬张量(np.0(pnt_云形状[0]))
i=0
对于pnt_云中的pnt:
xyz_pnt=焊炬.马特穆尔(T,pnt)
如果xyz_pnt[0]>0:
深度数组[i]=xyz\u pnt[0]
i+=1
返回深度数组
调用以下代码并计算运行时(使用%时间)将给出输出:

Out[190]: CPU times: user 670 ms, sys: 7.91 ms, total: 678 ms
Wall time: 674 ms
Out[199]: CPU times: user 6.15 s, sys: 28.1 ms, total: 6.18 s
Wall time: 6.09 s
注意:对torch.jit执行相同操作只会减少2秒

我原以为Pytork张量计算会快得多,因为Pytork在编译阶段分解代码的方式。我错过了什么


除了使用Numba,还有其他更快的方法吗?

为什么要使用for循环??
为什么计算3x3点积时只使用结果的第一个元素

您可以在一个
matmul
中完成所有数学运算:

带火炬的
。无梯度()
深度数组=torch.matmul(pnt_云,T[:1,:].T)#nx3点3x1->nx1
#因为你只想要非负面的结果
深度数组=火炬。最大值(深度数组,0)

因为您想将runtime与numpy进行比较,所以应该禁用。

关于速度,我从PyTorch论坛得到了以下回复:

  • 在Pytork中,1-3个元素的操作通常相当昂贵,因为张量创建的开销变得非常大(这包括设置单个元素),我认为这是这里的主要内容。这也是为什么JIT没有起到很大的作用(它只带走了Python的开销)和Numby的优势(例如,对depth_array[i]的赋值只是内存写入)

  • 如果在PyTorch和NumPy中有不同的BLAS后端,matmul本身的速度可能会有所不同


  • 你是如何将一个形状点(3,)与形状矩阵(4,4)相乘的?尺寸是否不兼容?Pytork是否可能正在为该操作积累梯度?哦,是的,我删除了第四个术语,以使问题更易于理解和概括,但忘记了减小另一个矩阵的大小。我已经编辑了这个问题,感谢您指出Natchiket在上面的问题中,我声明pnt_cld是一个100000 x 3矩阵,即每行为1 x 3。我将每个1 x 3向量乘以T(3x3)。[nx3点3x1->nx3不等于上述过程]我发现的另一件事是张量运算本身不会累积梯度。只有当操作涉及nn.model对象时,才会累积渐变。@dankpenny I更新了代码中有关矩阵大小的注释。因为你只使用结果的一个元素-你可以乘以矩阵的3x1行,而不是整个矩阵。哦,是的,我的坏哈哈!