Skip to content

Commit 7307b56

Browse files
jeremiedbbjnothman
authored andcommitted
MNT Update setup and travis to support OpenMP (scikit-learn#13053)
1 parent 1610094 commit 7307b56

File tree

3 files changed

+95
-3
lines changed

3 files changed

+95
-3
lines changed

build_tools/travis/install.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ then
2525
# export CCACHE_LOGFILE=/tmp/ccache.log
2626
# ~60M is used by .ccache when compiling from scratch at the time of writing
2727
ccache --max-size 100M --show-stats
28+
elif [ $TRAVIS_OS_NAME = "osx" ]
29+
then
30+
# install OpenMP not present by default on osx
31+
brew install libomp
32+
33+
# enable OpenMP support for Apple-clang
34+
export CC=/usr/bin/clang
35+
export CXX=/usr/bin/clang++
36+
export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp"
37+
export CFLAGS="$CFLAGS -I/usr/local/opt/libomp/include"
38+
export CXXFLAGS="$CXXFLAGS -I/usr/local/opt/libomp/include"
39+
export LDFLAGS="$LDFLAGS -L/usr/local/opt/libomp/lib -lomp"
40+
export DYLD_LIBRARY_PATH=/usr/local/opt/libomp/lib
41+
42+
# avoid error due to multiple OpenMP libraries loaded simultaneously
43+
export KMP_DUPLICATE_LIB_OK=TRUE
2844
fi
2945

3046
make_conda() {

doc/developers/advanced_installation.rst

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ Scikit-learn requires:
4646

4747
Building Scikit-learn also requires
4848

49-
- Cython >=0.28.5
49+
- Cython >=0.28.5
50+
- OpenMP
5051

5152
Running tests requires
5253

@@ -102,6 +103,31 @@ On Unix-like systems, you can simply type ``make`` in the top-level folder to
102103
build in-place and launch all the tests. Have a look at the ``Makefile`` for
103104
additional utilities.
104105

106+
Mac OSX
107+
-------
108+
109+
The default C compiler, Apple-clang, on Mac OSX does not directly support
110+
OpenMP. The first solution to build scikit-learn is to install another C
111+
compiler such as gcc or llvm-clang. Another solution is to enable OpenMP
112+
support on the default Apple-clang. In the following we present how to
113+
configure this second option.
114+
115+
You first need to install the OpenMP library::
116+
117+
brew install libomp
118+
119+
Then you need to set the following environment variables::
120+
121+
export CC=clang
122+
export CXX=clang++
123+
export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp"
124+
export CFLAGS="$CFLAGS -I/usr/local/opt/libomp/include"
125+
export CXXFLAGS="$CXXFLAGS -I/usr/local/opt/libomp/include"
126+
export LDFLAGS="$LDFLAGS -L/usr/local/opt/libomp/lib -lomp"
127+
export DYLD_LIBRARY_PATH=/usr/local/opt/libomp/lib
128+
129+
Finally you can build the package using the standard command.
130+
105131
Installing build dependencies
106132
=============================
107133

@@ -111,7 +137,7 @@ Linux
111137
Installing from source requires you to have installed the scikit-learn runtime
112138
dependencies, Python development headers and a working C/C++ compiler.
113139
Under Debian-based operating systems, which include Ubuntu::
114-
140+
115141
sudo apt-get install build-essential python3-dev python3-setuptools \
116142
python3-numpy python3-scipy \
117143
libatlas-dev libatlas3-base

setup.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,57 @@ def run(self):
102102
shutil.rmtree(os.path.join(dirpath, dirname))
103103

104104

105-
cmdclass = {'clean': CleanCommand}
105+
def get_openmp_flag(compiler):
106+
if sys.platform == "win32" and ('icc' in compiler or 'icl' in compiler):
107+
return ['/Qopenmp']
108+
elif sys.platform == "win32":
109+
return ['/openmp']
110+
elif sys.platform == "darwin" and ('icc' in compiler or 'icl' in compiler):
111+
return ['-openmp']
112+
elif sys.platform == "darwin" and 'openmp' in os.getenv('CPPFLAGS', ''):
113+
# -fopenmp can't be passed as compile flag when using Apple-clang.
114+
# OpenMP support has to be enabled during preprocessing.
115+
#
116+
# For example, our macOS wheel build jobs use the following environment
117+
# variables to build with Apple-clang and the brew installed "libomp":
118+
#
119+
# export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp"
120+
# export CFLAGS="$CFLAGS -I/usr/local/opt/libomp/include"
121+
# export LDFLAGS="$LDFLAGS -L/usr/local/opt/libomp/lib -lomp"
122+
# export DYLD_LIBRARY_PATH=/usr/local/opt/libomp/lib
123+
return ['']
124+
# Default flag for GCC and clang:
125+
return ['-fopenmp']
126+
127+
128+
OPENMP_EXTENSIONS = []
129+
130+
131+
# custom build_ext command to set OpenMP compile flags depending on os and
132+
# compiler
133+
# build_ext has to be imported after setuptools
134+
from numpy.distutils.command.build_ext import build_ext # noqa
135+
136+
137+
class build_ext_subclass(build_ext):
138+
def build_extensions(self):
139+
if hasattr(self.compiler, 'compiler'):
140+
compiler = self.compiler.compiler[0]
141+
else:
142+
compiler = self.compiler.__class__.__name__
143+
144+
openmp_flag = get_openmp_flag(compiler)
145+
146+
for e in self.extensions:
147+
if e.name in OPENMP_EXTENSIONS:
148+
e.extra_compile_args += openmp_flag
149+
e.extra_link_args += openmp_flag
150+
151+
build_ext.build_extensions(self)
152+
153+
154+
cmdclass = {'clean': CleanCommand, 'build_ext': build_ext_subclass}
155+
106156

107157
# Optional wheelhouse-uploader features
108158
# To automate release of binary packages for scikit-learn we need a tool

0 commit comments

Comments
 (0)