我有大量的向量三元组,我想计算它们的标量三元积,我可以
import numpy
n = 871
a = numpy.random.rand(n, 3)
b = numpy.random.rand(n, 3)
c = numpy.random.rand(n, 3)
# <a, b x c>
omega = numpy.einsum('ij, ij->i', a, numpy.cross(b, c))
但numpy.cross
相当慢,问题的对称性(Levi-Civita表达式为eps_{ijk} a_i b_j c_k
)表明可能有更好(更快)的方法来计算它,但我似乎想不出来。
有什么线索吗?
3条答案
按热度按时间htrmnn0y1#
这只是决定因素。
但是它更慢...
另一个等价解是
omega=dot(a,cross(b,c)).sum(1)
。但我认为你必须计算大约9(交叉)+3(点)+2(和)= 14个操作为每个det,所以它似乎是接近最优的。充其量你会赢得一个2因子在numpy。
如果速度至关重要,则必须使用低级别。
numba
是一种简单的方法,可在此处实现15倍的系数:一些测试:
jhiyze9q2#
我对答案中提到的方法做了比较,结果是:
@Divakar 's一点一点地打败了einsum-十字架。
为了完整起见,让我注意一下,还有一种方法完全依赖于点积和sqrt,参见here。这种方法比einsum-cross和slice-sum都要慢一些。
该图使用perfplot创建,
nfs0ujit3#
这里有一种方法利用
slicing
和求和我们可以将计算
c0, c1, c2
及其堆栈版本的前三个步骤替换为一行代码,如下所示:这将创建另一个
(n,3)
数组,该数组必须与a
一起使用以进行求和缩减,从而得到(n,)
形状的数组。使用所提出的slicing_summing
方法,我们通过对这三个切片求和直接得到(n,)
形状的数组,从而避免中间的(n,3)
数组。样品运行-
运行时间测试-