J'ai un ensemble de contractions que je voudrais optimiser ; pour les contractions, j'utilise np.einsum()
du module NumPy. L'exemple minimal reproductible est ici :
import numpy as np
from time import time
d1=2
d2=3
d3=100
a = np.random.rand( d1,d1,d1,d1,d2,d2,d2,d2,d3,d3 ) + 1j*np.random.rand( d1,d1,d1,d1,d2,d2,d2,d2,d3,d3 )
b = np.random.rand( d1,d1, d2,d2,d3,d3 ) + 1j*np.random.rand( d1,d1,d2,d2,d3,d3 )
c = np.random.rand( d1,d1, d2,d2,d3,d3 ) + 1j*np.random.rand( d1,d1,d2,d2,d3,d3 )
path_1 = 'abcdefghij,ckgojs,dlhpjs,klmnopqrst->abmnefqrit'
path_2 = 'abcdefghij,ckgoji,nbrfji,klmnopqrij->almdepqhij'
ts = time()
einsum_pathinfo = np.einsum_path(path_1, a, b, c, a )
term_a = np.einsum(path_1, a, b, c, a, optimize=einsum_pathinfo[0])
print("took", time()-ts)
ts = time()
einsum_pathinfo = np.einsum_path( path_2, a, b, c , a )
term_a = np.einsum(path_2, a, b, c, a, optimize=einsum_pathinfo[0])
print("took", time()-ts)
Les temps semblent se situer autour de ~2 secondes. J'ai également observé que einsum
n'est généralement pas multithreadé, et un seul cœur est utilisé à la place. Existe-t-il un autre moyen efficace d'effectuer de telles contractions ? (Peut-être avec Numba ?).