Ответ 1
(w/r/t последнее предложение OP: я не знаю такого метода numpy/scipy, но w/r/t Вопрос в заголовке OP (то есть, улучшая производительность NumPy dot), что ниже с другой стороны, мой ответ направлен на повышение производительности большинства шагов, включающих вашу функцию для Y).
Во-первых, это должно дать вам заметный импульс по методу NumPy dot ванили:
>>> from scipy.linalg import blas as FB
>>> vx = FB.dgemm(alpha=1., a=v1, b=v2, trans_b=True)
Обратите внимание, что два массива, v1, v2 находятся в порядке C_FORTRAN
Вы можете получить доступ к байтовому порядку массива NumPy через атрибут массива flags, например:
>>> c = NP.ones((4, 3))
>>> c.flags
C_CONTIGUOUS : True # refers to C-contiguous order
F_CONTIGUOUS : False # fortran-contiguous
OWNDATA : True
MASKNA : False
OWNMASKNA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
чтобы изменить порядок одного из массивов, чтобы оба они были выровнены, просто вызовите конструктор массива NumPy, пройдите в массив и установите соответствующий флаг порядка на True
>>> c = NP.array(c, order="F")
>>> c.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : True
MASKNA : False
OWNMASKNA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
Вы можете дополнительно оптимизировать, используя выравнивание порядка массива, чтобы уменьшить избыточное потребление памяти, вызванное копированием исходных массивов.
Но почему массивы копируются перед тем, как их передать точка?
Точечный продукт полагается на операции BLAS. Эти операции требуют массивов, хранящихся в C-смежном порядке - это ограничение, которое вызывает копирование массивов.
С другой стороны, транспонирование не влияет на копию, но, к сожалению, возвращает результат в порядке Fortran:
Следовательно, чтобы устранить узкое место производительности, вам необходимо устранить шаг предикатного массива; для этого просто требуется, чтобы оба массива располагались в C-смежном порядке *.
Итак, чтобы вычислить точку (A.T., A) без дополнительной копии:
>>> import scipy.linalg.blas as FB
>>> vx = FB.dgemm(alpha=1.0, a=A.T, b=A.T, trans_b=True)
В сумме выражение выше (вместе с инструкцией импорта предикатов) может заменить точку, чтобы обеспечить ту же функциональность, но более высокую производительность
вы можете связать это выражение с такой функцией:
>>> super_dot = lambda v, w: FB.dgemm(alpha=1., a=v.T, b=w.T, trans_b=True)