Матричное умножение
numpy работает независимо от внутренней структуры массива. Например, вот два C -упорядоченных массива:
>>> import numpy as np
>>> a = np.random.rand(10, 2, 4)
>>> b = np.random.rand(10, 4, 2)
>>> print('a', a.shape, a.strides)
>>> print('b', b.shape, b.strides)
a (10, 2, 4) (64, 32, 8)
b (10, 4, 2) (64, 16, 8)
Вот эквивалентные массивы в порядке Фортрана:
>>> af = np.asfortranarray(a)
>>> bf = np.asfortranarray(b)
>>> print('af', af.shape, af.strides)
>>> print('bf', bf.shape, bf.strides)
af (10, 2, 4) (8, 80, 160)
bf (10, 4, 2) (8, 80, 320)
Numpy обрабатывает эквивалентные массивы как эквивалентные, независимо от того, их внутренней компоновки:
>>> np.allclose(a, af) and np.allclose(b, bf)
True
Результаты умножения матриц не зависят от внутренней компоновки:
>>> np.allclose(a @ b, af @ bf)
True
, и вы даже можете смешивать макеты, если вы будете sh:
>>> np.allclose(a @ bf, af @ b)
True
Короче говоря, наиболее удобный способ использования массивов, упорядоченных по Фортрану, в numpy - не беспокоиться о внутренней компоновке массива: форма - это все, что имеет значение.
Если ваш формы массива отличаются от ожидаемых numpy matmul API , лучше всего изменить форму массивов, например, используя a.transpose(2, 0, 1) @ b.transpose(2, 0, 1)
или аналогичный, в зависимости от того, что подходит для вашего варианта использования, но не волнуйтесь: для C или смежных массивов Fortran эта операция только корректирует метаданные вокруг представления массива, но не приводит к копированию или переупорядочению основного буфера данных.