<p><strong>方法#1</strong></p>
<p>对于带有NumPy的向量化的一个,您可以在获得所有带有外部乘法的两两乘法后使用掩蔽一个,如下所示-</p>
<pre><code>def pairwise_multiply_masking(a):
return (a[:,None]*a)[~np.tri(len(a),k=-1,dtype=bool)]
</code></pre>
<p><strong>方法#2</strong></p>
<p>对于真正大的输入1D数组,我们可能需要使用迭代<code>slicing</code>方法,该方法使用一个循环-</p>
<pre><code>def pairwise_multiply_iterative_slicing(a):
n = len(a)
N = (n*(n+1))//2
out = np.empty(N, dtype=a.dtype)
c = np.r_[0,np.arange(n,0,-1)].cumsum()
for ii,(i,j) in enumerate(zip(c[:-1],c[1:])):
out[i:j] = a[ii:]*a[ii]
return out
</code></pre>
<p><strong>基准测试</strong></p>
<p>我们将在设置中包括<a href="https://stackoverflow.com/a/62012545/">^{<cd2>} and ^{<cd3>} from @orlp's solution</a></p>
<p>使用<a href="https://github.com/droyed/benchit" rel="nofollow noreferrer">^{<cd4>}</a>包(打包在一起的一些基准测试工具;免责声明:我是它的作者)对建议的解决方案进行基准测试</p>
<pre><code>import benchit
funcs = [pairwise_multiply_masking, pairwise_multiply_iterative_slicing, pairwise_products_numba, pairwise_products]
in_ = [np.random.rand(n) for n in [10,50,100,200,500,1000,5000]]
t = benchit.timings(funcs, in_)
t.plot(logx=True, save='timings.png')
t.speedups(-1).plot(logx=True, logy=False, save='speedups.png')
</code></pre>
<p>结果(超过<code>pairwise_products</code>的计时和加速)——</p>
<p><a href="https://i.stack.imgur.com/dOf75.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/dOf75.png" alt="enter image description here"/></a></p>
<p><a href="https://i.stack.imgur.com/xXyKI.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xXyKI.png" alt="enter image description here"/></a></p>
<p>从绘图趋势可以看出,对于真正大型的阵列,基于切片的阵列将开始获胜,否则矢量化阵列将表现出色</p>
<p><strong>建议</strong></p>
<ul>
<li>我们还可以研究<code>numexpr</code>,以便对大型数组更有效地执行外部乘法</李>
</ul>