setup.py 8 KB
Newer Older
yan.yan's avatar
yan.yan committed
1
2
3
4
5
6
7
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Note: To use the 'upload' functionality of this file, you must:
#   $ pip install twine

import io
traveller59's avatar
traveller59 committed
8
import os
yan.yan's avatar
yan.yan committed
9
import shutil
10
import sys
11
from pathlib import Path
yan.yan's avatar
yan.yan committed
12
13
14
15
16
17
18
from shutil import rmtree
from typing import List

import pccm
from pccm.extension import ExtCallback, PCCMBuild, PCCMExtension
from setuptools import Command, find_packages, setup
from setuptools.extension import Extension
yan.yan's avatar
yan.yan committed
19
from ccimport import compat
20
21
import subprocess 
import re 
yan.yan's avatar
yan.yan committed
22
23
24
25
26

# Package meta-data.
NAME = 'spconv'
RELEASE_NAME = NAME
deps = ["cumm"]
yan.yan's avatar
yan.yan committed
27
cuda_ver = os.environ.get("CUMM_CUDA_VERSION", "")
yan.yan's avatar
v2.1  
yan.yan committed
28
29
30
31
32
33
34
35
36
37
38
39
40
# is_ci_build = cuda_ver != ""
# if not cuda_ver:
#     nvcc_version = subprocess.check_output(["nvcc", "--version"
#                                             ]).decode("utf-8").strip()
#     nvcc_version_str = nvcc_version.split("\n")[3]
#     version_str: str = re.findall(r"release (\d+.\d+)",
#                                     nvcc_version_str)[0]
#     cuda_ver = version_str

if cuda_ver:
    cuda_ver = cuda_ver.replace(".", "") # 10.2 to 102

    RELEASE_NAME += "-cu{}".format(cuda_ver)
yan.yan's avatar
yan.yan committed
41
    deps = ["cumm-cu{}>=0.3.2".format(cuda_ver)]
yan.yan's avatar
v2.1  
yan.yan committed
42
else:
yan.yan's avatar
yan.yan committed
43
    deps = ["cumm>=0.3.2"]
yan.yan's avatar
v2.1  
yan.yan committed
44
45


46

yan.yan's avatar
yan.yan committed
47
48
49
50
DESCRIPTION = 'spatial sparse convolution'
URL = 'https://github.com/traveller59/spconv'
EMAIL = 'yanyan.sub@outlook.com'
AUTHOR = 'Yan Yan'
51
REQUIRES_PYTHON = '>=3.7'
yan.yan's avatar
yan.yan committed
52
53
54
VERSION = None

# What packages are required for this module to be executed?
55
REQUIRED = ["pccm>=0.4.0", "ccimport>=0.4.0", "pybind11>=2.6.0", "fire", "numpy", *deps]
yan.yan's avatar
yan.yan committed
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

# What packages are optional?
EXTRAS = {
    # 'fancy feature': ['django'],
}

# The rest you shouldn't have to touch too much :)
# ------------------------------------------------
# Except, perhaps the License and Trove Classifiers!
# If you do change the License, remember to change the Trove Classifier for that!

here = os.path.abspath(os.path.dirname(__file__))
sys.path.append(str(Path(__file__).parent))

# Import the README and use it as the long-description.
# Note: this will only work if 'README.md' is present in your MANIFEST.in file!
try:
    with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
        long_description = '\n' + f.read()
except FileNotFoundError:
    long_description = DESCRIPTION

# Load the package's __version__.py module as a dictionary.
about = {}
if not VERSION:
    with open('version.txt', 'r') as f:
        version = f.read().strip()
else:
    version = VERSION
cwd = os.path.dirname(os.path.abspath(__file__))

87

yan.yan's avatar
yan.yan committed
88
89
90
91
92
93
94
95
def _convert_build_number(build_number):
    parts = build_number.split(".")
    if len(parts) == 2:
        return "{}{:03d}".format(int(parts[0]), int(parts[1]))
    elif len(parts) == 1:
        return build_number
    else:
        raise NotImplementedError
96

97

yan.yan's avatar
yan.yan committed
98
99
100
101
102
env_suffix = os.environ.get("SPCONV_VERSION_SUFFIX", "")
if env_suffix != "":
    version += ".dev{}".format(_convert_build_number(env_suffix))
version_path = os.path.join(cwd, NAME, '__version__.py')
about['__version__'] = version
traveller59's avatar
traveller59 committed
103

yan.yan's avatar
yan.yan committed
104
105
with open(version_path, 'w') as f:
    f.write("__version__ = '{}'\n".format(version))
tusimple's avatar
tusimple committed
106

yan.yan's avatar
yan.yan committed
107
108
class UploadCommand(Command):
    """Support setup.py upload."""
yanyan's avatar
yanyan committed
109

yan.yan's avatar
yan.yan committed
110
111
    description = 'Build and publish the package.'
    user_options = []
traveller59's avatar
traveller59 committed
112

yan.yan's avatar
yan.yan committed
113
114
115
116
    @staticmethod
    def status(s):
        """Prints things in bold."""
        print('\033[1m{0}\033[0m'.format(s))
traveller59's avatar
traveller59 committed
117

yan.yan's avatar
yan.yan committed
118
119
120
121
122
    def initialize_options(self):
        pass

    def finalize_options(self):
        pass
traveller59's avatar
traveller59 committed
123
124
125

    def run(self):
        try:
yan.yan's avatar
yan.yan committed
126
127
            self.status('Removing previous builds...')
            rmtree(os.path.join(here, 'dist'))
traveller59's avatar
traveller59 committed
128
        except OSError:
yan.yan's avatar
yan.yan committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
            pass

        self.status('Building Source and Wheel (universal) distribution...')
        os.system('{0} setup.py sdist bdist_wheel --universal'.format(
            sys.executable))

        self.status('Uploading the package to PyPI via Twine...')
        os.system('twine upload dist/*')

        self.status('Pushing git tags...')
        os.system('git tag v{0}'.format(about['__version__']))
        os.system('git push --tags')

        sys.exit()



disable_jit = os.getenv("SPCONV_DISABLE_JIT", None)

if disable_jit is not None and disable_jit == "1":
    cmdclass = {
        'upload': UploadCommand,
        'build_ext': PCCMBuild,
    }
153
    from cumm.gemm.main import GemmMainUnitTest
154
155
    from spconv.core import SHUFFLE_SIMT_PARAMS, SHUFFLE_VOLTA_PARAMS, SHUFFLE_TURING_PARAMS, SHUFFLE_AMPERE_PARAMS
    from spconv.core import IMPLGEMM_SIMT_PARAMS, IMPLGEMM_VOLTA_PARAMS, IMPLGEMM_TURING_PARAMS, IMPLGEMM_AMPERE_PARAMS
yan.yan's avatar
v2.1  
yan.yan committed
156
157
    from cumm.conv.main import ConvMainUnitTest
    from cumm.constants import CUMM_CPU_ONLY_BUILD
yan.yan's avatar
yan.yan committed
158
    from spconv.csrc.sparse.all import SpconvOps
yan.yan's avatar
yan.yan committed
159
    from spconv.csrc.utils import BoxOps, PointCloudCompress
160
    from spconv.csrc.hash.core import HashTable
yan.yan's avatar
yan.yan committed
161
    from cumm.common import CompileInfo
yan.yan's avatar
yan.yan committed
162
163
164
    from spconv.csrc.sparse.alloc import ExternalAllocator
    from spconv.csrc.sparse.convops import GemmTunerSimple, ExternalSpconvMatmul
    from spconv.csrc.sparse.convops import ConvTunerSimple, ConvGemmOps
yan.yan's avatar
yan.yan committed
165
    from spconv.csrc.sparse.inference import InferenceOps
yan.yan's avatar
yan.yan committed
166
167
168
169
170
171
172
173
    all_shuffle = SHUFFLE_SIMT_PARAMS + SHUFFLE_VOLTA_PARAMS + SHUFFLE_TURING_PARAMS + SHUFFLE_AMPERE_PARAMS
    all_imp = (IMPLGEMM_SIMT_PARAMS + IMPLGEMM_VOLTA_PARAMS +
               IMPLGEMM_TURING_PARAMS + IMPLGEMM_AMPERE_PARAMS)
    all_shuffle = list(filter(lambda x: not x.is_nvrtc, all_shuffle))
    all_imp = list(filter(lambda x: not x.is_nvrtc, all_imp))

    cu = GemmMainUnitTest(all_shuffle)
    convcu = ConvMainUnitTest(all_imp)
yan.yan's avatar
v2.1  
yan.yan committed
174
    convcu.namespace = "cumm.conv.main"
yan.yan's avatar
yan.yan committed
175
176

    cu.namespace = "cumm.gemm.main"
yan.yan's avatar
v2.1  
yan.yan committed
177
178
179
180
181
182
183
    std = "c++17"
    if cuda_ver:
        cuda_ver_number = int(cuda_ver)
        if cuda_ver_number < 110:
            std = "c++14" 
        else:
            std = "c++17"
Yan Yan's avatar
Yan Yan committed
184
    if not CUMM_CPU_ONLY_BUILD:
yan.yan's avatar
yan.yan committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        gemmtuner = GemmTunerSimple(cu)
        gemmtuner.namespace = "csrc.sparse.convops.gemmops"
        convtuner = ConvTunerSimple(convcu)
        convtuner.namespace = "csrc.sparse.convops.convops"
        convops = ConvGemmOps(gemmtuner, convtuner)
        convops.namespace = "csrc.sparse.convops.spops"
    else:
        gemmtuner = GemmTunerSimple(None)
        gemmtuner.namespace = "csrc.sparse.convops.gemmops"
        convtuner = ConvTunerSimple(None)
        convtuner.namespace = "csrc.sparse.convops.convops"
        convops = ConvGemmOps(gemmtuner, convtuner)
        convops.namespace = "csrc.sparse.convops.spops"
    cus = [gemmtuner, convtuner,
        convops, SpconvOps(), BoxOps(), HashTable(), CompileInfo(), 
yan.yan's avatar
yan.yan committed
200
        ExternalAllocator(), PointCloudCompress(),
yan.yan's avatar
yan.yan committed
201
        ExternalSpconvMatmul(), InferenceOps()]
yan.yan's avatar
yan.yan committed
202
203
    if not CUMM_CPU_ONLY_BUILD:
        cus.extend([cu, convcu])
yan.yan's avatar
yan.yan committed
204
    ext_modules: List[Extension] = [
yan.yan's avatar
v2.1  
yan.yan committed
205
        PCCMExtension(cus,
yan.yan's avatar
yan.yan committed
206
                      "spconv/core_cc",
yan.yan's avatar
yan.yan committed
207
                      Path(__file__).resolve().parent / "spconv",
yan.yan's avatar
yan.yan committed
208
                      std=std,
Yan Yan's avatar
Yan Yan committed
209
                      disable_pch=True,
Yan Yan's avatar
Yan Yan committed
210
                      verbose=True)
yan.yan's avatar
yan.yan committed
211
212
213
214
215
216
217
218
    ]
else:
    cmdclass = {
        'upload': UploadCommand,
    }
    ext_modules = []

# Where the magic happens:
traveller59's avatar
traveller59 committed
219
setup(
yan.yan's avatar
yan.yan committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
    name=RELEASE_NAME,
    version=about['__version__'],
    description=DESCRIPTION,
    long_description=long_description,
    long_description_content_type='text/markdown',
    author=AUTHOR,
    author_email=EMAIL,
    python_requires=REQUIRES_PYTHON,
    url=URL,
    packages=find_packages(exclude=('tests', )),
    # If your package is a single module, use this instead of 'packages':
    # py_modules=['mypackage'],
    entry_points={
        'console_scripts': [],
    },
    install_requires=REQUIRED,
    extras_require=EXTRAS,
    include_package_data=True,
yan.yan's avatar
yan.yan committed
238
    license='Apache License 2.0',
yan.yan's avatar
yan.yan committed
239
240
241
    classifiers=[
        # Trove classifiers
        # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
yan.yan's avatar
yan.yan committed
242
        'License :: OSI Approved :: Apache Software License',
yan.yan's avatar
yan.yan committed
243
244
245
246
247
248
249
        'Programming Language :: Python',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: Implementation :: CPython',
    ],
    # $ setup.py publish support.
    cmdclass=cmdclass,
    ext_modules=ext_modules,
traveller59's avatar
traveller59 committed
250
)