|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import os |
|
from os.path import join as pjoin |
|
from setuptools import setup |
|
from distutils.extension import Extension |
|
from Cython.Distutils import build_ext |
|
import numpy as np |
|
|
|
|
|
def find_in_path(name, path): |
|
"Find a file in a search path" |
|
|
|
|
|
for dir in path.split(os.pathsep): |
|
binpath = pjoin(dir, name) |
|
if os.path.exists(binpath): |
|
return os.path.abspath(binpath) |
|
return None |
|
|
|
|
|
def locate_cuda(): |
|
"""Locate the CUDA environment on the system |
|
Returns a dict with keys 'home', 'nvcc', 'include', and 'lib64' |
|
and values giving the absolute path to each directory. |
|
Starts by looking for the CUDAHOME env variable. If not found, everything |
|
is based on finding 'nvcc' in the PATH. |
|
""" |
|
|
|
|
|
if 'CUDAHOME' in os.environ: |
|
home = os.environ['CUDAHOME'] |
|
nvcc = pjoin(home, 'bin', 'nvcc') |
|
else: |
|
|
|
default_path = pjoin(os.sep, 'usr', 'local', 'cuda', 'bin') |
|
nvcc = find_in_path('nvcc', os.environ['PATH'] + os.pathsep + default_path) |
|
if nvcc is None: |
|
raise EnvironmentError('The nvcc binary could not be ' |
|
'located in your $PATH. Either add it to your path, or set $CUDAHOME') |
|
home = os.path.dirname(os.path.dirname(nvcc)) |
|
|
|
cudaconfig = {'home':home, 'nvcc':nvcc, |
|
'include': pjoin(home, 'include'), |
|
'lib64': pjoin(home, 'lib64')} |
|
for k, v in cudaconfig.items(): |
|
if not os.path.exists(v): |
|
raise EnvironmentError('The CUDA %s path could not be located in %s' % (k, v)) |
|
|
|
return cudaconfig |
|
CUDA = locate_cuda() |
|
|
|
|
|
|
|
try: |
|
numpy_include = np.get_include() |
|
except AttributeError: |
|
numpy_include = np.get_numpy_include() |
|
|
|
|
|
def customize_compiler_for_nvcc(self): |
|
"""inject deep into distutils to customize how the dispatch |
|
to gcc/nvcc works. |
|
If you subclass UnixCCompiler, it's not trivial to get your subclass |
|
injected in, and still have the right customizations (i.e. |
|
distutils.sysconfig.customize_compiler) run on it. So instead of going |
|
the OO route, I have this. Note, it's kindof like a wierd functional |
|
subclassing going on.""" |
|
|
|
|
|
self.src_extensions.append('.cu') |
|
|
|
|
|
default_compiler_so = self.compiler_so |
|
super = self._compile |
|
|
|
|
|
|
|
|
|
def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): |
|
if os.path.splitext(src)[1] == '.cu': |
|
|
|
self.set_executable('compiler_so', CUDA['nvcc']) |
|
|
|
|
|
postargs = extra_postargs['nvcc'] |
|
else: |
|
postargs = extra_postargs['gcc'] |
|
|
|
super(obj, src, ext, cc_args, postargs, pp_opts) |
|
|
|
self.compiler_so = default_compiler_so |
|
|
|
|
|
self._compile = _compile |
|
|
|
|
|
|
|
class custom_build_ext(build_ext): |
|
def build_extensions(self): |
|
customize_compiler_for_nvcc(self.compiler) |
|
build_ext.build_extensions(self) |
|
|
|
|
|
ext_modules = [ |
|
Extension( |
|
"cpu_nms", |
|
["cpu_nms.pyx"], |
|
extra_compile_args={'gcc': ["-Wno-cpp", "-Wno-unused-function"]}, |
|
include_dirs = [numpy_include] |
|
), |
|
Extension('gpu_nms', |
|
['nms_kernel.cu', 'gpu_nms.pyx'], |
|
library_dirs=[CUDA['lib64']], |
|
libraries=['cudart'], |
|
language='c++', |
|
runtime_library_dirs=[CUDA['lib64']], |
|
|
|
|
|
|
|
extra_compile_args={'gcc': ["-Wno-unused-function"], |
|
'nvcc': ['-arch=sm_35', |
|
'--ptxas-options=-v', |
|
'-c', |
|
'--compiler-options', |
|
"'-fPIC'"]}, |
|
include_dirs = [numpy_include, CUDA['include']] |
|
), |
|
] |
|
|
|
setup( |
|
name='nms', |
|
ext_modules=ext_modules, |
|
|
|
cmdclass={'build_ext': custom_build_ext}, |
|
) |
|
|