Хотя я не думаю, что вы можете добиться гораздо большего успеха, чем применение поворота по точкам, все же есть место для значительной экономии.
(1) Использование экспоненциальной матрицы для вычисления простых матриц вращения смехотворно расточительно,Намного лучше использовать скалярную экспоненту или синус и косинус
(2) В меньшей степени то же самое относится к использованию перекрестного произведения для тасования.Индексирование здесь предпочтительнее.
(3) Порядок умножения матриц имеет значение.При массовом вращении более трех векторов самое левое умножение должно выполняться последним.
Вместе эти меры ускоряют вычисление в шесть раз:
(вставьте перед последними двумя строками оригиналаскрипт)
from scipy.linalg import block_diag
from timeit import timeit
def rot_euler_better(v, xyz):
TD = np.multiply.outer(np.exp(1j * np.asanyarray(xyz)), [[1], [1j]]).view(float)
x, y, z = (block_diag(1, TD[i])[np.ix_(*2*(np.arange(-i, 3-i),))] for i in range(3))
return v @ (x @ y @ z)
# example
xyz = np.pi * np.array((1/6, -2/3, 1/4))
print("Same result:",
np.allclose(rot_euler(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz),
rot_euler_better(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz))
print("OP: ", timeit(lambda: rot_euler(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz), number=1000), "ms")
print("optimized:", timeit(lambda: rot_euler_better(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz), number=1000), "ms")
ex, ey, ez = map(np.reshape, rot_euler_better(np.array((*map(np.ravel, (ex, ey, ez)),)).T, xyz).T, map(np.shape, (ex, ey, ez)))
Вывод:
Same result: True
OP: 2.1019406360574067 ms
optimized: 0.3485010238364339 ms