【问题标题】:fastest way to find the magnitude (length) squared of a vector field找到向量场的大小(长度)平方的最快方法
【发布时间】:2013-11-20 18:03:44
【问题描述】:

我有一个很大的矢量场,其中场很大(例如 512^3;但不一定是正方形)并且矢量是 2D 或 3D(例如形状是 [512, 512, 512, 2] 或 [512 , 512, 512, 3])。

计算向量平方大小的标量场的最快方法是什么?

我可以遍历每个方向,即

import numpy as np
shp = [256,256,256,3]                       # Shape of vector field
vf = np.arange(3*(256**3)).reshape(shp)     # Create vector field
sf = np.zeros(shp[:3])                      # Create scalar field for result

for ii in range(shp[0]):
    for jj in range(shp[1]):
        for kk in range(shp[2]):
            sf[ii,jj,kk] = np.dot( vf[ii,jj,kk,:] , vf[ii,jj,kk,:] )

但是速度很慢,有什么更快的吗?

【问题讨论】:

标签: python math optimization vector numpy


【解决方案1】:

最快的可能是np.einsum:

np.einsum('...j,...j->...', vf, vf)

上面的代码告诉 numpy 抓取它的输入,并通过将相应的值相乘并将它们加在一起来减少每个输入的最后一个维度。您的数据集存在溢出问题,因为幅度不适合 32 位整数,这是 np.arange 的默认返回值。您可以通过将返回 dtype 指定为 np.int64np.double 来解决这个问题:

>>> np.einsum('...j,...j->...', vf,vf)[-1, -1, -1]
-603979762
>>> np.einsum('...j,...j->...', vf,vf).dtype
dtype('int32')

>>> np.einsum('...j,...j->...', vf,vf, dtype=np.int64)[-1, -1, -1]
7599823767207950
>>> np.einsum('...j,...j->...', vf,vf, dtype=np.double)[-1, -1, -1]
7599823767207950.0

【讨论】:

  • 谢谢@Jaime,您能否解释或评论这意味着什么和/或为什么它是最佳的?
  • 哇。 einsum 刚刚度过了我的一周。
  • 另一种——也许更明确的——方法是使用np.sum(vf * vf, axis=-1)。然而,一个快速测试(对于给定的数组大小)表明einsum 版本的速度是原来的两倍多(我猜是因为它避免使用临时的vf * vf 数组)。
  • @bogatron Einsum 可以使用 SSE2,而 numpy ufuncs 不能在 1.7 中使用,请参阅 here
  • @Ophion 感谢您的链接。这是非常有用的。如果您对此有不同的解释,请纠正我,但您在链接中显示的结果向我表明我上面的评论仍然有效,因为这里提出的问题最接近您的上一个示例,其中 einsum 仍然比 ufunc 解决方案快得多(即使使用 SSE2)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 2017-08-29
相关资源
最近更新 更多