283
setup.py
283
setup.py
@@ -23,9 +23,8 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
from sysconfig import get_paths
|
||||
from typing import Dict, List
|
||||
|
||||
from setuptools import Extension, find_packages, setup
|
||||
from setuptools import Command, Extension, find_packages, setup
|
||||
from setuptools.command.build_ext import build_ext
|
||||
from setuptools.command.build_py import build_py
|
||||
from setuptools.command.develop import develop
|
||||
@@ -45,19 +44,18 @@ ROOT_DIR = os.path.dirname(__file__)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def check_or_set_default_env(cmake_args,
|
||||
env_name,
|
||||
env_variable,
|
||||
default_path=""):
|
||||
def check_or_set_default_env(cmake_args, env_name, env_variable, default_path=""):
|
||||
if env_variable is None:
|
||||
logging.warning(
|
||||
f"No {env_name} found in your environment, pleause try to set {env_name} "
|
||||
"if you customize the installation path of this library, otherwise default "
|
||||
"path will be adapted during build this project")
|
||||
logging.warning(f"Set default {env_name}: {default_path}")
|
||||
"No %s found in your environment, please try to set %s if you customize the installation path of this "
|
||||
"library, otherwise default path will be adapted during build this project",
|
||||
env_name,
|
||||
env_name,
|
||||
)
|
||||
logging.warning("Set default %s: %s", env_name, default_path)
|
||||
env_variable = default_path
|
||||
else:
|
||||
logging.info(f"Found existing {env_name}: {env_variable}")
|
||||
logging.info("Found existing %s: %s", env_name, env_variable)
|
||||
# cann package seems will check this environments in cmake, need write this env variable back.
|
||||
if env_name == "ASCEND_HOME_PATH":
|
||||
os.environ["ASCEND_HOME_PATH"] = env_variable
|
||||
@@ -65,47 +63,177 @@ def check_or_set_default_env(cmake_args,
|
||||
return cmake_args
|
||||
|
||||
|
||||
envs = load_module_from_path("envs",
|
||||
os.path.join(ROOT_DIR, "vllm_ascend", "envs.py"))
|
||||
def get_value_from_lines(lines: list[str], key: str) -> str:
|
||||
for line in lines:
|
||||
line = " ".join(line.split())
|
||||
if key in line:
|
||||
return line.split(":")[-1].strip()
|
||||
return ""
|
||||
|
||||
|
||||
def get_chip_type() -> str:
|
||||
try:
|
||||
# Get NPU ID
|
||||
npu_info_lines = subprocess.check_output(["npu-smi", "info", "-l"]).decode().strip().split("\n")
|
||||
npu_id = int(get_value_from_lines(npu_info_lines, "NPU ID"))
|
||||
|
||||
# Stage 1: query board info without -c flag
|
||||
board_info_lines = (
|
||||
subprocess.check_output(["npu-smi", "info", "-t", "board", "-i", str(npu_id)]).decode().strip().split("\n")
|
||||
)
|
||||
|
||||
# Check if Chip Name exists (Ascend950 includes it directly)
|
||||
chip_name = get_value_from_lines(board_info_lines, "Chip Name")
|
||||
|
||||
# Stage 2: query with -c flag only if Chip Name not found (A2/A3/310P)
|
||||
if not chip_name:
|
||||
chip_info_lines = (
|
||||
subprocess.check_output(["npu-smi", "info", "-t", "board", "-i", str(npu_id), "-c", "0"])
|
||||
.decode()
|
||||
.strip()
|
||||
.split("\n")
|
||||
)
|
||||
else:
|
||||
# Ascend950 already has complete info
|
||||
chip_info_lines = board_info_lines
|
||||
|
||||
# Extract required fields
|
||||
chip_name = get_value_from_lines(chip_info_lines, "Chip Name")
|
||||
chip_type = get_value_from_lines(chip_info_lines, "Chip Type")
|
||||
npu_name = get_value_from_lines(chip_info_lines, "NPU Name")
|
||||
|
||||
if "310" in chip_name:
|
||||
# 310P case
|
||||
assert chip_type
|
||||
return (chip_type + chip_name).lower()
|
||||
elif "910" in chip_name:
|
||||
if chip_type:
|
||||
# A2 case
|
||||
assert not npu_name
|
||||
return (chip_type + chip_name).lower()
|
||||
else:
|
||||
# A3 case
|
||||
assert npu_name
|
||||
return (chip_name + "_" + npu_name).lower()
|
||||
elif "950" in chip_name:
|
||||
assert npu_name
|
||||
return (chip_name + "_" + npu_name).lower()
|
||||
elif "a2g3" in chip_name.lower():
|
||||
# A2 case: CH version of the HDK
|
||||
return "ascend910b1"
|
||||
else:
|
||||
raise ValueError(f"Unable to recognize chip name: {chip_name}, please manually set env SOC_VERSION")
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise RuntimeError(f"Get chip info failed: {e}")
|
||||
except FileNotFoundError:
|
||||
logging.warning(
|
||||
"npu-smi command not found, if this is an npu envir, please check if npu driver is installed correctly."
|
||||
)
|
||||
return ""
|
||||
|
||||
|
||||
envs = load_module_from_path("envs", os.path.join(ROOT_DIR, "vllm_ascend", "envs.py"))
|
||||
|
||||
if not envs.SOC_VERSION:
|
||||
soc_version = get_chip_type()
|
||||
if not soc_version:
|
||||
raise RuntimeError(
|
||||
"Could not determine chip type automatically via 'npu-smi'. "
|
||||
"This can happen in a CPU-only environment. "
|
||||
"Please set the 'SOC_VERSION' environment variable to specify the target chip, for example:\n"
|
||||
' - Atlas A2: export SOC_VERSION="ascend910b1"\n'
|
||||
' - Atlas A3: export SOC_VERSION="ascend910_9391"\n'
|
||||
' - Atlas 300I: export SOC_VERSION="ascend310p1"\n'
|
||||
' - Atlas A5: export SOC_VERSION="<value starting with ascend950>"\n'
|
||||
"You can also refer to the SOC_VERSION defaults in Dockerfile*."
|
||||
)
|
||||
envs.SOC_VERSION = soc_version
|
||||
|
||||
|
||||
def gen_build_info():
|
||||
soc_version = envs.SOC_VERSION
|
||||
|
||||
soc_to_device = {
|
||||
"910b": "A2",
|
||||
"910c": "A3",
|
||||
"310p": "_310P",
|
||||
"ascend910b1": "A2",
|
||||
"ascend910b2": "A2",
|
||||
"ascend910b2c": "A2",
|
||||
"ascend910b3": "A2",
|
||||
"ascend910b4": "A2",
|
||||
"ascend910b4-1": "A2",
|
||||
"ascend910_9391": "A3",
|
||||
"ascend910_9381": "A3",
|
||||
"ascend910_9372": "A3",
|
||||
"ascend910_9392": "A3",
|
||||
"ascend910_9382": "A3",
|
||||
"ascend910_9362": "A3",
|
||||
"ascend310p1": "_310P",
|
||||
"ascend310p3": "_310P",
|
||||
"ascend310p5": "_310P",
|
||||
"ascend310p7": "_310P",
|
||||
"ascend310p3vir01": "_310P",
|
||||
"ascend310p3vir02": "_310P",
|
||||
"ascend310p3vir04": "_310P",
|
||||
"ascend310p3vir08": "_310P",
|
||||
}
|
||||
if "ascend950" in soc_version:
|
||||
device_type = "A5"
|
||||
else:
|
||||
assert soc_version in soc_to_device, (
|
||||
f"Undefined soc_version: {soc_version}. Please file an issue to vllm-ascend."
|
||||
)
|
||||
device_type = soc_to_device[soc_version]
|
||||
|
||||
package_dir = os.path.join(ROOT_DIR, "vllm_ascend", "_build_info.py")
|
||||
with open(package_dir, "w+") as f:
|
||||
f.write("# Auto-generated file\n")
|
||||
f.write(f"__device_type__ = '{device_type}'\n")
|
||||
logging.info("Generated _build_info.py with SOC version: %s", soc_version)
|
||||
|
||||
|
||||
class CMakeExtension(Extension):
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
cmake_lists_dir: str = ".",
|
||||
**kwargs) -> None:
|
||||
def __init__(self, name: str, cmake_lists_dir: str = ".", **kwargs) -> None:
|
||||
super().__init__(name, sources=[], py_limited_api=False, **kwargs)
|
||||
self.cmake_lists_dir = os.path.abspath(cmake_lists_dir)
|
||||
|
||||
|
||||
class custom_develop(develop):
|
||||
def run(self):
|
||||
gen_build_info()
|
||||
super().run()
|
||||
|
||||
|
||||
class custom_build_info(build_py):
|
||||
def run(self):
|
||||
gen_build_info()
|
||||
super().run()
|
||||
|
||||
|
||||
class build_and_install_aclnn(Command):
|
||||
description = "Build and install AclNN by running build_aclnn.sh"
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
soc_version = envs.SOC_VERSION
|
||||
if not soc_version:
|
||||
raise ValueError(
|
||||
"SOC version is not set. Please set SOC_VERSION environment variable."
|
||||
)
|
||||
if "310" in soc_version and not envs.COMPILE_CUSTOM_KERNELS:
|
||||
raise ValueError(
|
||||
"SOC version 310 only supports custom kernels. Please set COMPILE_CUSTOM_KERNELS=1 to enable custom kernels."
|
||||
)
|
||||
|
||||
package_dir = os.path.join(ROOT_DIR, "vllm_ascend", "_build_info.py")
|
||||
with open(package_dir, "w+") as f:
|
||||
f.write('# Auto-generated file\n')
|
||||
f.write(f"__soc_version__ = '{soc_version}'\n")
|
||||
f.write(
|
||||
f"__sleep_mode_enabled__ = {envs.COMPILE_CUSTOM_KERNELS}\n")
|
||||
logging.info(
|
||||
f"Generated _build_info.py with SOC version: {soc_version}")
|
||||
super().run()
|
||||
try:
|
||||
print("Running bash build_aclnn.sh ...")
|
||||
subprocess.check_call(["bash", "csrc/build_aclnn.sh", ROOT_DIR, envs.SOC_VERSION])
|
||||
print("build_aclnn.sh executed successfully!")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error running build_aclnn.sh: {e}")
|
||||
raise SystemExit(e.returncode)
|
||||
|
||||
|
||||
class cmake_build_ext(build_ext):
|
||||
# A dict of extension directories that have been configured.
|
||||
did_config: Dict[str, bool] = {}
|
||||
did_config: dict[str, bool] = {}
|
||||
|
||||
#
|
||||
# Determine number of compilation jobs
|
||||
@@ -140,9 +268,9 @@ class cmake_build_ext(build_ext):
|
||||
# Default use release mode to compile the csrc code
|
||||
# Turbo now support compiled with Release, Debug and RelWithDebugInfo
|
||||
if envs.CMAKE_BUILD_TYPE is None or envs.CMAKE_BUILD_TYPE not in [
|
||||
"Debug",
|
||||
"Release",
|
||||
"RelWithDebugInfo",
|
||||
"Debug",
|
||||
"Release",
|
||||
"RelWithDebugInfo",
|
||||
]:
|
||||
envs.CMAKE_BUILD_TYPE = "Release"
|
||||
cmake_args += [f"-DCMAKE_BUILD_TYPE={envs.CMAKE_BUILD_TYPE}"]
|
||||
@@ -164,20 +292,18 @@ class cmake_build_ext(build_ext):
|
||||
)
|
||||
|
||||
# find PYTHON_EXECUTABLE
|
||||
check_or_set_default_env(cmake_args, "PYTHON_EXECUTABLE",
|
||||
sys.executable)
|
||||
check_or_set_default_env(cmake_args, "PYTHON_EXECUTABLE", sys.executable)
|
||||
|
||||
# find PYTHON_INCLUDE_PATH
|
||||
check_or_set_default_env(cmake_args, "PYTHON_INCLUDE_PATH",
|
||||
get_paths()["include"])
|
||||
check_or_set_default_env(cmake_args, "PYTHON_INCLUDE_PATH", get_paths()["include"])
|
||||
|
||||
# ccache and ninja can not be applied at ascendc kernels now
|
||||
|
||||
try:
|
||||
# if pybind11 is installed via pip
|
||||
pybind11_cmake_path = (subprocess.check_output(
|
||||
[python_executable, "-m", "pybind11",
|
||||
"--cmakedir"]).decode().strip())
|
||||
pybind11_cmake_path = (
|
||||
subprocess.check_output([python_executable, "-m", "pybind11", "--cmakedir"]).decode().strip()
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
# else specify pybind11 path installed from source code on CI container
|
||||
raise RuntimeError(f"CMake configuration failed: {e}")
|
||||
@@ -190,7 +316,13 @@ class cmake_build_ext(build_ext):
|
||||
|
||||
cmake_args += [f"-DCMAKE_PREFIX_PATH={pybind11_cmake_path}"]
|
||||
|
||||
cmake_args += [f"-DSOC_VERSION={envs.SOC_VERSION}"]
|
||||
soc_version_map = {
|
||||
"910b": "ascend910b1",
|
||||
"910c": "ascend910_9392",
|
||||
"310p": "ascend310p1",
|
||||
}
|
||||
CANN_SOC_VERSION = soc_version_map.get(envs.SOC_VERSION, envs.SOC_VERSION)
|
||||
cmake_args += [f"-DSOC_VERSION={CANN_SOC_VERSION}"]
|
||||
|
||||
# Override the base directory for FetchContent downloads to $ROOT/.deps
|
||||
# This allows sharing dependencies between profiles,
|
||||
@@ -202,8 +334,7 @@ class cmake_build_ext(build_ext):
|
||||
|
||||
torch_npu_command = "python3 -m pip show torch-npu | grep '^Location:' | awk '{print $2}'"
|
||||
try:
|
||||
torch_npu_path = subprocess.check_output(
|
||||
torch_npu_command, shell=True).decode().strip()
|
||||
torch_npu_path = subprocess.check_output(torch_npu_command, shell=True).decode().strip()
|
||||
torch_npu_path += "/torch_npu"
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise RuntimeError(f"Retrieve torch version version failed: {e}")
|
||||
@@ -211,6 +342,11 @@ class cmake_build_ext(build_ext):
|
||||
# add TORCH_NPU_PATH
|
||||
cmake_args += [f"-DTORCH_NPU_PATH={torch_npu_path}"]
|
||||
|
||||
# Pass VLLM_ASCEND_ENABLE_BATCH_MEMCPY to CMake if explicitly set.
|
||||
# When unset (None), CMake will auto-detect from CANN headers.
|
||||
if envs.VLLM_ASCEND_ENABLE_BATCH_MEMCPY is not None:
|
||||
cmake_args += [f"-DVLLM_ASCEND_ENABLE_BATCH_MEMCPY={envs.VLLM_ASCEND_ENABLE_BATCH_MEMCPY}"]
|
||||
|
||||
build_tool = []
|
||||
# TODO(ganyi): ninja and ccache support for ascend c auto codegen. now we can only use make build
|
||||
# if which('ninja') is not None:
|
||||
@@ -218,7 +354,7 @@ class cmake_build_ext(build_ext):
|
||||
# Default build tool to whatever cmake picks.
|
||||
|
||||
cmake_args += [source_dir]
|
||||
logging.info(f"cmake config command: {cmake_args}")
|
||||
logging.info("cmake config command: %s", cmake_args)
|
||||
try:
|
||||
subprocess.check_call(cmake_args, cwd=self.build_temp)
|
||||
except subprocess.CalledProcessError as e:
|
||||
@@ -280,22 +416,36 @@ class cmake_build_ext(build_ext):
|
||||
# copy back to build folder for editable build
|
||||
if isinstance(self.distribution.get_command_obj("develop"), develop):
|
||||
import shutil
|
||||
|
||||
for root, _, files in os.walk(self.build_temp):
|
||||
for file in files:
|
||||
if file.endswith(".so"):
|
||||
src_path = os.path.join(root, file)
|
||||
dst_path = os.path.join(self.build_lib, "vllm_ascend",
|
||||
file)
|
||||
dst_path = os.path.join(self.build_lib, "vllm_ascend", file)
|
||||
shutil.copy(src_path, dst_path)
|
||||
print(f"Copy: {src_path} -> {dst_path}")
|
||||
|
||||
# copy back _cann_ops_custom directory
|
||||
src_cann_ops_custom = os.path.join(ROOT_DIR, "vllm_ascend", "_cann_ops_custom")
|
||||
dst_cann_ops_custom = os.path.join(self.build_lib, "vllm_ascend", "_cann_ops_custom")
|
||||
if os.path.exists(src_cann_ops_custom):
|
||||
import shutil
|
||||
|
||||
if os.path.exists(dst_cann_ops_custom):
|
||||
shutil.rmtree(dst_cann_ops_custom)
|
||||
shutil.copytree(src_cann_ops_custom, dst_cann_ops_custom)
|
||||
print(f"Copy: {src_cann_ops_custom} -> {dst_cann_ops_custom}")
|
||||
|
||||
def run(self):
|
||||
# First, run the standard build_ext command to compile the extensions
|
||||
if envs.COMPILE_CUSTOM_KERNELS:
|
||||
# First, ensure ACLNN custom-ops is built and installed.
|
||||
self.run_command("build_aclnn")
|
||||
|
||||
# Then, run the standard build_ext command to compile the extensions
|
||||
super().run()
|
||||
|
||||
|
||||
class custom_install(install):
|
||||
|
||||
def run(self):
|
||||
self.run_command("build_ext")
|
||||
install.run(self)
|
||||
@@ -328,10 +478,10 @@ def read_readme() -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def get_requirements() -> List[str]:
|
||||
def get_requirements() -> list[str]:
|
||||
"""Get Python package dependencies from requirements.txt."""
|
||||
|
||||
def _read_requirements(filename: str) -> List[str]:
|
||||
def _read_requirements(filename: str) -> list[str]:
|
||||
with open(get_path(filename)) as f:
|
||||
requirements = f.read().strip().split("\n")
|
||||
resolved_requirements = []
|
||||
@@ -352,9 +502,11 @@ def get_requirements() -> List[str]:
|
||||
|
||||
|
||||
cmdclass = {
|
||||
"develop": custom_develop,
|
||||
"build_py": custom_build_info,
|
||||
"build_aclnn": build_and_install_aclnn,
|
||||
"build_ext": cmake_build_ext,
|
||||
"install": custom_install
|
||||
"install": custom_install,
|
||||
}
|
||||
|
||||
setup(
|
||||
@@ -371,11 +523,10 @@ setup(
|
||||
project_urls={
|
||||
"Homepage": "https://github.com/vllm-project/vllm-ascend",
|
||||
},
|
||||
# TODO: Add 3.12 back when torch-npu support 3.12
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: Information Technology",
|
||||
@@ -384,14 +535,18 @@ setup(
|
||||
"Topic :: Scientific/Engineering :: Information Analysis",
|
||||
],
|
||||
packages=find_packages(exclude=("docs", "examples", "tests*", "csrc")),
|
||||
python_requires=">=3.9",
|
||||
python_requires=">=3.10",
|
||||
install_requires=get_requirements(),
|
||||
ext_modules=ext_modules,
|
||||
cmdclass=cmdclass,
|
||||
extras_require={},
|
||||
entry_points={
|
||||
"vllm.platform_plugins": ["ascend = vllm_ascend:register"],
|
||||
"vllm.general_plugins":
|
||||
["ascend_enhanced_model = vllm_ascend:register_model"],
|
||||
"vllm.general_plugins": [
|
||||
"ascend_kv_connector = vllm_ascend:register_connector",
|
||||
"ascend_model_loader = vllm_ascend:register_model_loader",
|
||||
"ascend_service_profiling = vllm_ascend:register_service_profiling",
|
||||
"ascend_model = vllm_ascend:register_model",
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user