Essentially, I'm using opt_einsum for some tensor network calculations, and a significant proportion of time is spent in contract_path, even for relatively large sized tensors and pre-calculated paths.
Specifically, a huge number of contractions with the same indices and shapes are performed over and over again and I already cache these using the path from contract_path. However, it seems even with the path supplied, a large amount of time is spent parsing the input, in can_blas, parse_einsum_input etc.
My suggestion would be something like:
shapes = [(2, 3), (3, 4), (4, 5)]
my_expr = einsum_expression("ab,bc,cd->ad", *shapes)
for _ in many_repeats:
...
x, y, z = (rand(s) for s in shapes)
out = my_expr(x, y, z)
...
I.e. it would only accept arrays of the same dimensions (and probably an out argument) and would otherwise skip all parsing, using a contraction_list stored within the function.
Anyway, I'm about to knock something up to test for myself, but thought it might be of more general interest.
This would be great to have in the framework. I think perhaps the best approach is to break this loop into a separate function that can be called without a lot of checking.
Essentially, I'm using
opt_einsum
for some tensor network calculations, and a significant proportion of time is spent incontract_path
, even for relatively large sized tensors and pre-calculated paths.Specifically, a huge number of contractions with the same indices and shapes are performed over and over again and I already cache these using the path from
contract_path
. However, it seems even with the path supplied, a large amount of time is spent parsing the input, incan_blas
,parse_einsum_input
etc.My suggestion would be something like:
I.e. it would only accept arrays of the same dimensions (and probably an
out
argument) and would otherwise skip all parsing, using acontraction_list
stored within the function.Anyway, I'm about to knock something up to test for myself, but thought it might be of more general interest.