Repository: pymc-devs/pymc
Pull request: Compilation error workaround
This applies platform-specific flags (for Mac and Windows) to circumvent compilation errors for certain models.

Closes #3695 

Problem statement:
Theano compilation error when using marginal Gaussian processes
When using marginal Gaussian processes, parameterizing the marginal likelihood such as the following:

```python
    y_ = gp.marginal_likelihood("y", X=X, Xu=Xu, y=y, noise=σ)
```

causes a compilation failure in Theano:

```
Exception: ("Compilation failed (return status=1): /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:510:27: error: non-constant-expression cannot be narrowed from type 'npy_intp' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].     int init_totals[2] = {V3_n0, V3_n1};.                           ^~~~~. /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:510:27: note: insert an explicit cast to silence this issue.     int init_totals[2] = {V3_n0, V3_n1};.                           ^~~~~.                           static_cast<int>( ). /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:510:34: error: non-constant-expression cannot be narrowed from type 'npy_intp' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].     int init_totals[2] = {V3_n0, V3_n1};.                                  ^~~~~. /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:510:34: note: insert an explicit cast to silence this issue.     int init_totals[2] = {V3_n0, V3_n1};.                                  ^~~~~.                                  static_cast<int>( ). /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:522:9: error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].         V3_stride0, V3_stride1, .         ^~~~~~~~~~. /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:522:9: note: insert an explicit cast to silence this issue.         V3_stride0, V3_stride1, .         ^~~~~~~~~~.         static_cast<int>( ). /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:522:21: error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing].         V3_stride0, V3_stride1, .                     ^~~~~~~~~~. /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:522:21: note: insert an explicit cast to silence this issue.         V3_stride0, V3_stride1, .                     ^~~~~~~~~~.                     static_cast<int>( ). /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:524:1: error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing]. V1_stride0, V1_stride1. ^~~~~~~~~~. /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:524:1: note: insert an explicit cast to silence this issue. V1_stride0, V1_stride1. ^~~~~~~~~~. static_cast<int>( ). /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:524:13: error: non-constant-expression cannot be narrowed from type 'ssize_t' (aka 'long') to 'int' in initializer list [-Wc++11-narrowing]. V1_stride0, V1_stride1.             ^~~~~~~~~~. /Users/cfonnesbeck/.theano/compiledir_Darwin-19.0.0-x86_64-i386-64bit-i386-3.7.3-64/tmp5ctmpymk/mod.cpp:524:13: note: insert an explicit cast to silence this issue. V1_stride0, V1_stride1.             ^~~~~~~~~~.             static_cast<int>( ). 6 errors generated.. ", '[Elemwise{mul,no_inplace}(TensorConstant{[[ 0.9442 ..78980556]]}, <TensorType(float64, (True, True))>)]')
```
Looks like a numpy-related issue; mine is 1.17.3.

## Versions and main components

* PyMC3 Version: 3.7 from current master
* Theano Version: 1.0.4
* Python Version: 3.7
* Operating system: macOS
* How did you install PyMC3: pip (from master)

Hints from issue discussion:
Downgrading numpy to 1.16 does not seem to help.
A work-around is to have theano ignore the compilation errors:

```python
theano.config.gcc.cxxflags = "-Wno-c++11-narrowing"
```
If you're on Windows, setting 

```
theano.config.mode = 'FAST_COMPILE' 
```
fixed it for me. I'm using `numpy==1.16.5` and `theano==1.0.4`, same pymc3 version. 

From [here](https://github.com/Theano/Theano/issues/6678), it seems to be an issue with how theano interacts with the multiprocessing library.

Should we set this to a default? @fonnesbeck 
Seems like the expedient way to get fixes out to users quickly.

Commit message: Added Theano flags to __init__.py

Patch to review:
diff --git a/pymc3/__init__.py b/pymc3/__init__.py
index 8c851adfed..d83053ebe5 100644
--- a/pymc3/__init__.py
+++ b/pymc3/__init__.py
@@ -6,7 +6,15 @@
 from .distributions import transforms
 from .glm import *
 from . import gp
-from .math import logaddexp, logsumexp, logit, invlogit, expand_packed_triangular, probit, invprobit
+from .math import (
+    logaddexp,
+    logsumexp,
+    logit,
+    invlogit,
+    expand_packed_triangular,
+    probit,
+    invprobit,
+)
 from .model import *
 from .model_graph import model_to_graphviz
 from . import ode
@@ -28,9 +36,18 @@
 from .tests import test
 
 from .data import *
+import theano
+import platform
+
+system = platform.system()
+if system == "Windows":
+    theano.config.mode = "FAST_COMPILE"
+elif system == "Darwin":
+    theano.config.gcc.cxxflags = "-Wno-c++11-narrowing"
 
 import logging
-_log = logging.getLogger('pymc3')
+
+_log = logging.getLogger("pymc3")
 if not logging.root.handlers:
     _log.setLevel(logging.INFO)
     if len(_log.handlers) == 0:


Code review comments:
diff_hunk: @@ -28,9 +36,18 @@
 from .tests import test
 
 from .data import *
+import theano
path: pymc3/__init__.py
text: @user1:
This looks good to go, but I would wrap the whole thing in a mangled function, so that the top-level namespace does not get too busy.


```python
def __set_theano_flags():
    import theano
    import platform
    ...

__set_theano_flags()
```

@author:
That's a good idea.