Quando preciso gerar uma matriz de índices N-dimensional em ordem C, tento algumas abordagens diferentes do NumPy.
O mais rápido para matrizes maiores, mas menos legível:
np.stack(np.meshgrid(*[np.arange(i, dtype=dtype) for i in sizes], indexing="ij"), axis=-1).reshape(-1, len(sizes))
Mais legível com bom desempenho:
np.ascontiguousarray(np.indices(sizes, dtype=dtype).reshape(len(sizes), -1).T)
Aqui, não tenho certeza se a cópia ascontiguousarray é realmente necessária ou se há uma maneira melhor de garantir que o resultado esteja na ordem C sem forçar uma cópia.
Mais legível, mas de longe o mais lento:
np.vstack([*np.ndindex(sizes)], dtype=dtype)
A conversão do iterador é bastante lenta para matrizes maiores.
Existe uma maneira integrada mais direta e legível de fazer isso que corresponda ao desempenho de np.meshgrid ou np.indices usando NumPy? Caso contrário, as abordagens meshgrid ou indices podem ser otimizadas para evitar cópias de memória desnecessárias (como ascontiguousarray), garantindo ainda que o array seja C-contíguo?
Exemplo:
sizes = (3, 1, 2)
idx = np.ascontiguousarray(np.indices(sizes).reshape(len(sizes), -1).T)
print(idx)
print(f"C_CONTIGUOUS: {idx.flags['C_CONTIGUOUS']}")
# [[0 0 0]
# [0 0 1]
# [1 0 0]
# [1 0 1]
# [2 0 0]
# [2 0 1]]
# C_CONTIGUOUS: True