Einsum path helpers#
- ivy.utils.einsum_path_helpers.can_dot(inputs, result, idx_removed)[source]#
Check if we can use BLAS (np.tensordot) call and its beneficial to do so.
- Parameters:
inputs (list of str) – Specifies the subscripts for summation.
result (str) – Resulting summation.
idx_removed (set) – Indices that are removed in the summation
- Returns:
type (bool) – Returns true if BLAS should and can be used, else False
Notes
If the operations is BLAS level 1 or 2 and is not already aligned we default back to einsum as the memory movement to copy is more costly than the operation itself.
Examples
# Standard GEMM operation >>> can_dot([‘ij’, ‘jk’], ‘ik’, set(‘j’)) True # Can use the standard BLAS, but requires odd data movement >>> can_dot([‘ijj’, ‘jk’], ‘ik’, set(‘j’)) False # DDOT where the memory is not aligned >>> can_dot([‘ijk’, ‘ikj’], ‘’, set(‘ijk’)) False
- ivy.utils.einsum_path_helpers.compute_size_by_dict(indices, idx_dict)[source]#
Compute the product of the elements in indices based on the dictionary idx_dict.
- Parameters:
indices (iterable) – Indices to base the product on.
idx_dict (dictionary) – Dictionary of index sizes
- Returns:
ret (int) – The resulting product.
Examples
>>> compute_size_by_dict('abbc', {'a': 2, 'b':3, 'c':5}) 90
- ivy.utils.einsum_path_helpers.find_contraction(positions, input_sets, output_set)[source]#
Find the contraction for a given set of input and output sets.
- Parameters:
positions (iterable) – Integer positions of terms used in the contraction.
input_sets (list) – List of sets that represent the lhs side of the einsum subscript
output_set (set) – Set that represents the rhs side of the overall einsum subscript
- Returns:
new_result (set) – The indices of the resulting contraction
remaining (list) – List of sets that have not been contracted, the new set is appended to the end of this list
idx_removed (set) – Indices removed from the entire contraction
idx_contraction (set) – The indices used in the current contraction
Examples
# A simple dot product test case >>> pos = (0, 1) >>> isets = [set(‘ab’), set(‘bc’)] >>> oset = set(‘ac’) >>> find_contraction(pos, isets, oset) ({‘a’, ‘c’}, [{‘a’, ‘c’}], {‘b’}, {‘a’, ‘b’, ‘c’}) # A more complex case with additional terms in the contraction >>> pos = (0, 2) >>> isets = [set(‘abd’), set(‘ac’), set(‘bdc’)] >>> oset = set(‘ac’) >>> find_contraction(pos, isets, oset) ({‘a’, ‘c’}, [{‘a’, ‘c’}, {‘a’, ‘c’}], {‘b’, ‘d’}, {‘a’, ‘b’, ‘c’, ‘d’})
- ivy.utils.einsum_path_helpers.flop_count(idx_contraction, inner, num_terms, size_dictionary)[source]#
Compute the number of FLOPS in the contraction.
- Parameters:
idx_contraction (iterable) – The indices involved in the contraction
inner (bool) – Does this contraction require an inner product?
num_terms (int) – The number of terms in a contraction
size_dictionary (dict) – The size of each of the indices in idx_contraction
- Returns:
flop_count (int) – The total number of FLOPS required for the contraction.
Examples
>>> flop_count('abc', False, 1, {'a': 2, 'b':3, 'c':5}) 30
>>> flop_count('abc', True, 2, {'a': 2, 'b':3, 'c':5}) 60
- ivy.utils.einsum_path_helpers.greedy_path(input_sets, output_set, idx_dict, memory_limit)[source]#
Find the path by contracting the best pair until the input list is exhausted. The best pair is found by minimizing the tuple
(-prod(indices_removed), cost)
. What this amounts to is prioritizing matrix multiplication or inner product operations, then Hadamard like operations, and finally outer operations. Outer products are limited bymemory_limit
. This algorithm scales cubically with respect to the number of elements in the listinput_sets
.- Parameters:
input_sets (list) – List of sets that represent the lhs side of the einsum subscript
output_set (set) – Set that represents the rhs side of the overall einsum subscript
idx_dict (dictionary) – Dictionary of index sizes
memory_limit (int) – The maximum number of elements in a temporary array
- Returns:
path (list) – The greedy contraction order within the memory limit constraint.
Examples
>>> isets = [set('abd'), set('ac'), set('bdc')] >>> oset = set() >>> idx_sizes = {'a': 1, 'b':2, 'c':3, 'd':4} >>> greedy_path(isets, oset, idx_sizes, 5000) [(0, 2), (0, 1)]
- ivy.utils.einsum_path_helpers.optimal_path(input_sets, output_set, idx_dict, memory_limit)[source]#
Compute all possible pair contractions, sieves the results based on
memory_limit
and returns the lowest cost path. This algorithm scales factorial with respect to the elements in the listinput_sets
.- Parameters:
input_sets (list) – List of sets that represent the lhs side of the einsum subscript
output_set (set) – Set that represents the rhs side of the overall einsum subscript
idx_dict (dictionary) – Dictionary of index sizes
memory_limit (int) – The maximum number of elements in a temporary array
- Returns:
path (list) – The optimal contraction order within the memory limit constraint.
Examples
>>> isets = [set('abd'), set('ac'), set('bdc')] >>> oset = set() >>> idx_sizes = {'a': 1, 'b':2, 'c':3, 'd':4} >>> optimal_path(isets, oset, idx_sizes, 5000) [(0, 2), (0, 1)]
- ivy.utils.einsum_path_helpers.parse_einsum_input(operands, subscripts=None)[source]#
Reproduction of einsum c side einsum parsing in python.
- Returns:
input_strings (str) – Parsed input strings
output_string (str) – Parsed output string
operands (list of array_like) – The operands to use in the numpy contraction
Examples
The operand list is simplified to reduce printing:
>>> np.random.seed(123) >>> a = np.random.rand(4, 4) >>> b = np.random.rand(4, 4, 4) >>> parse_einsum_input(('...a,...a->...', a, b)) ('za,xza', 'xz', [a, b]) # may vary >>> parse_einsum_input((a, [Ellipsis, 0], b, [Ellipsis, 0])) ('za,xza', 'xz', [a, b]) # may vary
- ivy.utils.einsum_path_helpers.parse_possible_contraction(positions, input_sets, output_set, idx_dict, memory_limit, path_cost, naive_cost)[source]#
Compute the cost (removed size + flops) and resultant indices for performing the contraction specified by
positions
.- Parameters:
positions (tuple of int) – The locations of the proposed tensors to contract.
input_sets (list of sets) – The indices found on each tensors.
output_set (set) – The output indices of the expression.
idx_dict (dict) – Mapping of each index to its size.
memory_limit (int) – The total allowed size for an intermediary tensor.
path_cost (int) – The contraction cost so far.
naive_cost (int) – The cost of the unoptimized expression.
- Returns:
cost ((int, int)) – A tuple containing the size of any indices removed, and the flop cost.
positions (tuple of int) – The locations of the proposed tensors to contract.
new_input_sets (list of sets) – The resulting new list of indices if this proposed contraction is performed.
- ivy.utils.einsum_path_helpers.update_other_results(results, best)[source]#
Update the positions and provisional input_sets of
results
based on performing the contraction resultbest
. Remove any involving the tensors contracted.- Parameters:
results (list) – List of contraction results produced by
_parse_possible_contraction
.best (list) – The best contraction of
results
i.e. the one that will be performed.
- Returns:
mod_results (list) – The list of modified results, updated with outcome of
best
contraction.
This should have hopefully given you an overview of the einsum_path_helpers submodule, if you have any questions, please feel free to reach out on our discord!