inner1d
これをいじって、最速を見つけました。ただし、その機能は内部的なものであるため、より堅牢なアプローチを使用することです
numpy.einsum("ij,ij->i", a, b)
さらに良いのは、合計が最初の次元で発生するようにメモリを調整することです。
a = numpy.random.rand(3, n)
b = numpy.random.rand(3, n)
numpy.einsum("ij,ij->j", a, b)
の場合10 ** 3 <= n <= 10 ** 6
、これは最速の方法であり、転置されていない同等の方法の最大2倍の速度です。最大値は、レベル2のキャッシュが最大になっているときに発生します(約。) 2 * 10 ** 4
。
sum
転置されたメイションは、転置されていない同等のものよりもはるかに高速であることに注意してください。
プロットはperfplot(私の小さなプロジェクト)で作成されました
import numpy
from numpy.core.umath_tests import inner1d
import perfplot
def setup(n):
a = numpy.random.rand(n, 3)
b = numpy.random.rand(n, 3)
aT = numpy.ascontiguousarray(a.T)
bT = numpy.ascontiguousarray(b.T)
return (a, b), (aT, bT)
b = perfplot.bench(
setup=setup,
n_range=[2 ** k for k in range(1, 25)],
kernels=[
lambda data: numpy.sum(data[0][0] * data[0][1], axis=1),
lambda data: numpy.einsum("ij, ij->i", data[0][0], data[0][1]),
lambda data: numpy.sum(data[1][0] * data[1][1], axis=0),
lambda data: numpy.einsum("ij, ij->j", data[1][0], data[1][1]),
lambda data: inner1d(data[0][0], data[0][1]),
],
labels=["sum", "einsum", "sum.T", "einsum.T", "inner1d"],
xlabel="len(a), len(b)",
)
b.save("out1.png")
b.save("out2.png", relative_to=3)