Repository: numpy/numpy

Issue:
DOC: default value of `optimize` in `numpy.einsum`
<!-- Please describe the issue in detail here, and fill in the fields below -->

In the documentation page https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.einsum.html, the default value of `optimize` is correctly stated to be `False` in the function signature, but erroneously stated to be `True` in the parameter description:

> optimize : {False, True, ‘greedy’, ‘optimal’}, optional
> Controls if intermediate optimization should occur. No optimization will occur if False and True will default to the ‘greedy’ algorithm. Also accepts an explicit contraction list from the np.einsum_path function. See np.einsum_path for more details. **Default is True**.

### Reproducing code example:

<!-- A short code example that reproduces the problem/missing feature. It should be
self-contained, i.e., possible to run as-is via 'python myproblem.py' -->

```python
import timeit
print(timeit.timeit("np.einsum('ea,fb,abcd,gc,hd->efgh', C, C, I, C, C, optimize = True)", 'import numpy as np; I = np.random.rand(10, 10, 10, 10); C = np.random.rand(10, 10)', number = 10))
print(timeit.timeit("np.einsum('ea,fb,abcd,gc,hd->efgh', C, C, I, C, C)", 'import numpy as np; I = np.random.rand(10, 10, 10, 10); C = np.random.rand(10, 10)', number = 10))
```

The second line should run much slower than the first line.

### Numpy/Python version information:

<!-- Output from 'import sys, numpy; print(numpy.__version__, sys.version)' -->
    1.15.1 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24) 
    [Clang 6.0 (clang-600.0.57)]



Discussion:
Yes, False is correct. There are some performance issues with very small arrays and generally a few subtle differences, so we can't default to True.
This is a small change, maybe you want to try to create a pull request (for documentation, even pressing the Edit button on github is fine, we try to start the commit message with `DOC: ...`).
Actually it seems that someone has beat me to it: PR #11234 fixes this problem. It seems that the PR has been merged into the master branch, but not into the 1.15.x branch.
While we are at it, there is another thing I'm uncertain about: the documentation describes `optimize` as "intermediate" optimization, but if my understanding of the code is correct, blas is only used when `optimize` is on, even if there are only two operands. This point turned out to be significant in my project, because OpenBLAS (and presumably some other implementations of blas) is not thread safe by default, and `einsum` seems to be thread safe otherwise.
What?! Blas should be thread safe! It might create many threads, but it should be thread safe for sure. Einsum won't use multiple threads normally otherwise, yes.

It is only typically an intermediate optimization, then it creates a more efficient order for einsum, but sometimes it might replace the einsum operation fully.

EDIT: To be clear, if there is a thread safety issue there, can you open a new issue about it?
That's #11046. Blas should be thread safe... as long as you
> * export OPENBLAS_NUM_THREADS=1 in the environment variables. Or
> * Call openblas_set_num_threads(1) in the application on runtime. Or
> * Build OpenBLAS single thread version, e.g. make USE_THREAD=0
Oh, didn't really follow that issue. Frankly, I think that is pretty damn bad!
@charris, just pinging you. We could backport gh-11234 if it really is just uncontroversial documentation. But since it seems larger, I am good with living with slightly incorrect docs for 1.15.x, doc backports is not something we commonly did/do.

Otherwise, can just close the issue.
Looks like it would be easier to just fix the documentation for the default value of `optimize`.

EDIT: Given how often this issue has come up, probably worth doing.

Resolving patch:
diff --git a/numpy/core/einsumfunc.py b/numpy/core/einsumfunc.py
--- a/numpy/core/einsumfunc.py
+++ b/numpy/core/einsumfunc.py
@@ -1028,7 +1028,7 @@ def einsum(*operands, **kwargs):
         Controls if intermediate optimization should occur. No optimization
         will occur if False and True will default to the 'greedy' algorithm.
         Also accepts an explicit contraction list from the ``np.einsum_path``
-        function. See ``np.einsum_path`` for more details. Default is True.
+        function. See ``np.einsum_path`` for more details. Defaults to False.
 
     Returns
     -------


Test patch: