forked from Dots-Infra/UltraEP
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.py
More file actions
171 lines (150 loc) · 5.82 KB
/
Copy pathsetup.py
File metadata and controls
171 lines (150 loc) · 5.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import ast
import re
import os
import subprocess
import setuptools
import importlib
from pathlib import Path
import torch
from torch.utils.cpp_extension import BuildExtension, CUDAExtension
current_dir = os.path.dirname(os.path.realpath(__file__))
# Wheel specific: the wheels only include the SO name of the host library `libnvshmem_host.so.X`
def get_nvshmem_host_lib_name(base_dir):
path = Path(base_dir).joinpath("lib")
for file in path.rglob("libnvshmem_host.so.*"):
return file.name
raise ModuleNotFoundError("libnvshmem_host.so not found")
def get_package_version():
with open(Path(current_dir) / "ultra_ep" / "__init__.py", "r") as f:
version_match = re.search(r"^__version__\s*=\s*(.*)$", f.read(), re.MULTILINE)
public_version = ast.literal_eval(version_match.group(1))
# noinspection PyBroadException
try:
status_cmd = ["git", "status", "--porcelain"]
status_output = subprocess.check_output(status_cmd).decode("ascii").strip()
if status_output:
print(
f"Warning: Git working directory is not clean. Uncommitted changes:\n{status_output}"
)
cmd = ["git", "rev-parse", "--short", "HEAD"]
revision = "+" + subprocess.check_output(cmd).decode("ascii").rstrip()
except:
revision = "+local"
return f"{public_version}{revision}"
def find_cpp_cuda_sources(root_dir="csrc"):
valid_exts = {".cpp", ".cc", ".cu"}
source_files = []
for dirpath, _, filenames in os.walk(root_dir):
for fname in filenames:
if Path(fname).suffix in valid_exts:
source_files.append(str(Path(dirpath) / fname))
return source_files
if __name__ == "__main__":
nvshmem_dir = os.getenv("NVSHMEM_DIR", None)
nvshmem_host_lib = "libnvshmem_host.so"
if nvshmem_dir is None:
spec = importlib.util.find_spec("nvidia.nvshmem")
if spec is None:
raise SystemExit(
"Unable to locate the nvidia.nvshmem package. "
"Install nvidia-nvshmem-cu12/13 or set NVSHMEM_DIR explicitly."
)
nvshmem_dir = spec.submodule_search_locations[0]
nvshmem_host_lib = get_nvshmem_host_lib_name(nvshmem_dir)
import nvidia.nvshmem as nvshmem # noqa: F401
elif not os.path.exists(Path(nvshmem_dir) / "lib" / nvshmem_host_lib):
nvshmem_host_lib = get_nvshmem_host_lib_name(nvshmem_dir)
assert os.path.exists(
nvshmem_dir
), f"The specified NVSHMEM directory does not exist: {nvshmem_dir}"
cxx_flags = [
"-O3",
"-Wno-deprecated-declarations",
"-Wno-unused-variable",
"-Wno-sign-compare",
"-Wno-reorder",
"-Wno-attributes",
]
nvcc_flags = ["-O3", "-Xcompiler", "-O3"]
sources = find_cpp_cuda_sources("csrc")
include_dirs = ["csrc/"]
library_dirs = []
nvcc_dlink = []
extra_link_args = []
# NVSHMEM flags
include_dirs.extend([f"{nvshmem_dir}/include"])
library_dirs.extend([f"{nvshmem_dir}/lib"])
nvcc_dlink.extend(["-dlink", f"-L{nvshmem_dir}/lib", "-lnvshmem_device"])
extra_link_args.extend(
[
"-lcuda",
f"-l:{nvshmem_host_lib}",
"-l:libnvshmem_device.a",
f"-Wl,-rpath,{nvshmem_dir}/lib",
"-Wl,--allow-multiple-definition",
]
)
# Auto-detect CUDA arch if not explicitly set
if "TORCH_CUDA_ARCH_LIST" not in os.environ:
result = subprocess.run(
["nvidia-smi", "--query-gpu=compute_cap", "--format=csv,noheader"],
capture_output=True,
text=True,
check=True,
)
compute_cap = result.stdout.strip().splitlines()[0].strip()
sm = int(compute_cap.replace(".", ""))
if sm == 90:
os.environ["TORCH_CUDA_ARCH_LIST"] = "9.0"
elif sm == 100:
os.environ["TORCH_CUDA_ARCH_LIST"] = "10.0"
else:
raise RuntimeError(
f"Unsupported CUDA compute capability: {compute_cap} (SM{sm}). "
"Only SM90 and SM100 are supported. "
"Set TORCH_CUDA_ARCH_LIST manually to override."
)
# Device linking against NVSHMEM and multiple CUDA translation units requires RDC.
nvcc_flags.extend(["-rdc=true", "--ptxas-options=--register-usage-level=10"])
# Compilation workaround for CUDA 13.x
if torch.version.cuda and torch.version.cuda.startswith("13."):
include_dirs.extend(["/usr/local/cuda/include/cccl/"])
# Disable aggressive PTX instructions
if int(os.getenv("DISABLE_AGGRESSIVE_PTX_INSTRS", "1")):
cxx_flags.append("-DDISABLE_AGGRESSIVE_PTX_INSTRS")
nvcc_flags.append("-DDISABLE_AGGRESSIVE_PTX_INSTRS")
# Put them together
extra_compile_args = {
"cxx": cxx_flags,
"nvcc": nvcc_flags,
}
if len(nvcc_dlink) > 0:
extra_compile_args["nvcc_dlink"] = nvcc_dlink
# Summary
print("Build summary:")
print(f" > Sources: {sources}")
print(f" > Includes: {include_dirs}")
print(f" > Libraries: {library_dirs}")
print(f" > Compilation flags: {extra_compile_args}")
print(f" > Link flags: {extra_link_args}")
print(f' > Arch list: {os.environ["TORCH_CUDA_ARCH_LIST"]}')
print(f" > NVSHMEM path: {nvshmem_dir}")
print()
setuptools.setup(
name="ultra_ep",
version=get_package_version(),
packages=setuptools.find_packages(include=["ultra_ep", "ultra_ep.*"]),
ext_modules=[
CUDAExtension(
name="ultra_ep._C",
include_dirs=include_dirs,
library_dirs=library_dirs,
sources=sources,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
)
],
cmdclass={
"build_ext": BuildExtension,
},
)