flopscope.numpy.linalg.multi_dot
fnp.linalg.multi_dot(arrays: 'Sequence[ArrayLike]', *, out: 'ArrayLike | None' = None) -> 'FlopscopeArray'[flopscope source][numpy source]
Compute the dot product of two or more arrays in a single function call, while automatically selecting the fastest evaluation order.
Adapted from NumPy docs np.linalg.multi_dot
Chain matmul. Cost: sum of optimal chain matmul costs (CLRS §15.2).
multi_dot chains flops.dot and uses optimal parenthesization
of the matrices [1]_ [2]_. Depending on the shapes of the matrices,
this can speed up the multiplication a lot.
If the first argument is 1-D it is treated as a row vector. If the last argument is 1-D it is treated as a column vector. The other arguments must be 2-D.
Think of multi_dot as:
def multi_dot(arrays): return functools.reduce(flops.dot, arrays)Parameters
- arrays:sequence of array_like
If the first argument is 1-D it is treated as row vector. If the last argument is 1-D it is treated as column vector. The other arguments must be 2-D.
- out:ndarray, optional
Output argument. This must have the exact kind that would be returned if it was not used. In particular, it must have the right type, must be C-contiguous, and its dtype must be the dtype that would be returned for
dot(a, b). This is a performance feature. Therefore, if these conditions are not met, an exception is raised, instead of attempting to be flexible.
Returns
- output:ndarray
Returns the dot product of the supplied arrays.
See also
- we.flops.dot dot multiplication with two arguments.
Notes
The cost for a matrix multiplication can be calculated with the following function:
def cost(A, B):
return A.shape[0] * A.shape[1] * B.shape[1]Assume we have three matrices .
The costs for the two different parenthesizations are as follows:
cost((AB)C) = 10*100*5 + 10*5*50 = 5000 + 2500 = 7500
cost(A(BC)) = 10*100*50 + 100*5*50 = 50000 + 25000 = 75000References
1
Cormen, "Introduction to Algorithms", Chapter 15.2, p. 370-3782
https://en.wikipedia.org/wiki/Matrix_chain_multiplicationExamples
multi_dot allows you to write:
>>> import flopscope.numpy as fnp
>>> from flops.linalg import multi_dot
>>> # Prepare some data
>>> A = flops.random.random((10000, 100))
>>> B = flops.random.random((100, 1000))
>>> C = flops.random.random((1000, 5))
>>> D = flops.random.random((5, 333))
>>> # the actual dot multiplication
>>> _ = multi_dot([A, B, C, D])instead of:
>>> _ = flops.dot(flops.dot(flops.dot(A, B), C), D)
>>> # or
>>> _ = A.dot(B).dot(C).dot(D)