serge-sans-paille / pythran

Ahead of Time compiler for numeric kernels
https://pythran.readthedocs.io
BSD 3-Clause "New" or "Revised" License
2k stars 193 forks source link

Pythran openmp issue #1045

Open RalphFS opened 6 years ago

RalphFS commented 6 years ago

Installing Pythran via Conda-forge causes openmp to stop working for both Pythran and Cython.

When I create a new Conda environment via

conda create -n new_env anaconda

at least Cython (0.28.5) seems to work correctly with fopenmp. But as soon as I add Pythran (0.8.5 / 0.8.7) via

conda install -n new_env -c conda-forge pythran

something will break.

For example, if I compile the following lines of code:

%%file resample_file.py
#pythran export resample(float[], float[], float[])
import numpy as np
def resample(qs, xs, rands):
    results = np.empty_like(qs)
    lookup = np.cumsum(qs)
    #omp parallel for
    for j, key in enumerate(rands):
        i = np.argmax(lookup > key)
        results[j] = xs[i]
    return results
!pythran resample_file.py -e -fopenmp
from resample_file import resample

...I get this error message:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-9-87227346d693> in <module>
----> 1 from resample_file import resample

ImportError: dlopen(/Users/rfs/resample_file.cpython-36m-darwin.so, 2): 
Symbol not found: _GOMP_parallel
  Referenced from: /Users/rfs/resample_file.cpython-36m-darwin.so
  Expected in: flat namespace
 in /Users/rfs/resample_file.cpython-36m-darwin.so

The strange thing is that after installing Pythran this error message also occurs with Cython code when using openmp.

I tried this on two different computers, both running MacOS Mojave and gcc 8.2. Also, for some reason, no .pythranrc file is created during installation.

serge-sans-paille commented 6 years ago

Also, for some reason, no .pythranrc is created That's normal. It's a customization point, the vanilla pythran does not need one.

The OpenMP issue is both strange and critical. Can your reproduce it on Linux, or is that specific to OSX? It looks like you're no longer linking with the system OpenMP, or that you need to force the OpenMP rpath. The reason why you encounter this problem is probably that pythran depends on a c++ compiler that gets installed alongside pythran, but this compiler references an improper libgomp...

See this ticket: https://github.com/gprMax/gprMax/issues/134 that proposes a -rpath based solution (the actual rpath value probably differs on your setup)

RalphFS commented 6 years ago

Thanks for your quick response. I will try to reproduce this with Linux.

The reason why you encounter this problem is probably that pythran depends on a c++ compiler that gets installed alongside pythran, but this compiler references an improper libgomp...

Yes, that looks very familiar to me... that would also explain another problem I noticed: The speed of a compiled Pythran program depends on the kernel used. Let's say I have two anaconda environments:

When I import Pythran code into the anaconda kernel, the code is extremely slow. However, if I choose the new_env kernel, Pythran programs are very fast...

Also, for openMP to work with Cython, I need to set the following parameters: %%cython

distutils: extra_compile_args=-fopenmp

distutils: extra_link_args=-fopenmp

distutils: extra_link_args=-Wl,-rpath,/usr/local/Cellar/gcc/8.2.0/lib/gcc/8/

Can I force the openMP rpath in Pythran as well?

With respect to the wrong linkage I can show you the output of my bash_profile file.

export PATH=/usr/local/bin:$PATH export PATH="/usr/local/bin:/anaconda3/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin" export CC=/usr/local/Cellar/gcc/8.2.0/bin/gcc-8 export CXX=/usr/local/Cellar/gcc/8.2.0/bin/g++-8 export CPP=/usr/local/Cellar/gcc/8.2.0/bin/cpp-8 export LD=/usr/local/Cellar/gcc/8.2.0/bin/gcc-8 alias c++=/usr/local/Cellar/gcc/8.2.0/bin/c++-8 alias g++=/usr/local/Cellar/gcc/8.2.0/bin/g++-8 alias gcc=/usr/local/Cellar/gcc/8.2.0/bin/gcc-8 alias cpp=/usr/local/Cellar/gcc/8.2.0/bin/cpp-8 alias ld=/usr/local/Cellar/gcc/8.2.0/bin/gcc-8 alias cc=/usr/local/Cellar/gcc/8.2.0/bin/gcc-8

Does that somehow cause openMP to stop working with Pythran?

serge-sans-paille commented 6 years ago

Can I force the openMP rpath in Pythran as well? yes, passing the same options to pythran would work

pythran stuff.py -Wl,-rpath,/usr/local/Cellar/gcc/8.2.0/lib/gcc/8/
RalphFS commented 6 years ago

Okay that works in the terminal but it doesn't work in combination with the pythran magic,right? unfortunately, that doesn't fix the issue. However, today i tested it on a linux machine and can confirm that on linux everything works as desired.

serge-sans-paille commented 6 years ago

@RalphFS #1057 should make it possible to use -Wl,stuff in a pythran magic. Can you confirm it's okay for you?

RalphFS commented 6 years ago

I think this would be more convenient if you work a lot with Jupyter notebooks but I am also happy with the terminal solution. Unfortunately this does not fix the openmp error message. I'm not familiar with c++, but if you have any other ideas, you're welcome to give me instructions that I can try under MacOS. I'm pretty sure it's related to Pythran or some package dependencies, since the problem doesn't occur until I install Pythran from conda-froge.

serge-sans-paille commented 6 years ago

@RalphFS can you try to just install gcc in a venv, and check if gcc is the not the origin of the problem?

RalphFS commented 6 years ago

You are talking about a virtual conda environment, right? In the meantime I also tried anaconda gcc 4.8... unfortunately without success. However, I was able to solve the problem artificially in the meantime. Apparently different compilation dependencies cause these problems.

I used the terminal command otool -L example.so to examine the dependencies and found that once Pythran is installed, the following command is obviously ignored by Cython and Pythran: -Wl,-rpath,/usr/local/Cellar/gcc/8.2.0/lib/gcc/8/

To fix the problem, I had to copy the files libgomp.a, libgomp.1.dylib, libgomp.dylib and libgomp.spec from /usr/local/Cellar/gcc/8.2.0/lib/gcc/8/ into the lib folder of my anaconda environment. I don't understand why -Wl,-rpath,/usr/local/Cellar/gcc/8.2.0/lib/gcc/8/ is ignored, but at least it works now