2矢量矩阵点积的性能

时间:2015-09-07 19:52:11

标签: python performance numpy dot-product

问题更侧重于计算的表现。

我有2个矢量矩阵。这意味着它们具有X,Y,Z的3个深度尺寸。矩阵的每个元素必须与另一个矩阵的相同位置上的元素制作点积。

这是一个简单而无效的代码:

# Angle in radians
d = np.arccos(np.multiply(a[:,:,0],b[:,:,0]) + np.multiply(a[:,:,1],b[:,:,1]) + np.multiply(a[:,:,2],b[:,:,2]))

但是,numpy函数可以加快计算速度,使代码更快:

$con = mysqli_connect('localhost', 'user', 'pass',"db");

if (mysqli_connect_errno()){
    die("Failed to connect to MySQL: " . mysqli_connect_error());
}
$coupon = $_GET['coupon'];
$sql = mysqli_prepare($con, "SELECT * FROM coupon WHERE coupon=?");
$sql->bind_param('s', $coupon);
$sql->execute();
$sql->store_result();
echo $sql;

但是,我想知道是否还有其他的sintaxis可以通过其他函数,索引改进上面这个... ...

第一个代码需要 4.658s ,而第二个代码需要 0.354s

2 个答案:

答案 0 :(得分:5)

你可以用np.einsum来做到这一点,它会在任何轴上相乘然后求和:

np.arccos(np.einsum('ijk,ijk->ij', a, b))

您在问题中发布的更直接的方法是使用np.sum,您沿着最后一个轴(-1)求和:

np.arccos(np.sum(a*b, -1))

他们都给出相同的答案,但einsum是最快的,sum是下一个:

In [36]: timeit np.arccos(np.einsum('ijk,ijk->ij', a, b))
10000 loops, best of 3: 20.4 µs per loop

In [37]: timeit e = np.arccos(np.sum(a*b, -1))
10000 loops, best of 3: 29.8 µs per loop

In [38]: %%timeit
   ....: d = np.arccos(np.multiply(a[:,:,0],b[:,:,0]) +
   ....:               np.multiply(a[:,:,1],b[:,:,1]) +
   ....:               np.multiply(a[:,:,2],b[:,:,2]))
   ....:
10000 loops, best of 3: 34.6 µs per loop

答案 1 :(得分:0)

Pythran编译器可以通过以下方式进一步优化原始表达式:

  • 删除临时数组
  • 使用SIMD说明
  • 使用多线程

正如这个例子所示:

$ cat cross.py
#pythran export cross(float[][][], float[][][])
import numpy as np
def cross(a,b):
    return np.arccos(np.multiply(a[:, :, 0], b[:, :, 0]) + np.multiply(a[:, :, 1],b[:, :, 1]) + np.multiply(a[:, :, 2], b[:, :, 2]))
$ python -m timeit -s 'import numpy as np; a = np.random.uniform(low=-1.0, high=1.0, size=(1000, 1000, 3)); b = np.random.uniform(low=-1.0, high=1.0, size=(1000, 1000, 3)); c = np.zeros((1000, 1000)); from cross import cross' 'cross(a,b)'
10 loops, best of 3: 35.4 msec per loop
$ pythran cross.py -DUSE_BOOST_SIMD -fopenmp -march=native
$ python -m timeit -s 'import numpy as np; a = np.random.uniform(low=-1.0, high=1.0, size=(1000, 1000, 3)); b = np.random.uniform(low=-1.0, high=1.0, size=(1000, 1000, 3)); c = np.zeros((1000, 1000)); from cross import cross' 'cross(a,b)'
100 loops, best of 3: 11.8 msec per loop