215 lines
6.3 KiB
Python
215 lines
6.3 KiB
Python
# Copyright 2024 xDiT team.
|
|
# Adapted from
|
|
# https://github.com/xdit-project/xDiT/blob/main/xfuser/envs.py
|
|
import os
|
|
from collections.abc import Callable
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
import torch
|
|
from packaging import version
|
|
from vllm.logger import init_logger
|
|
|
|
logger = init_logger(__name__)
|
|
|
|
if TYPE_CHECKING:
|
|
MASTER_ADDR: str = ""
|
|
MASTER_PORT: int | None = None
|
|
CUDA_HOME: str | None = None
|
|
LOCAL_RANK: int = 0
|
|
CUDA_VISIBLE_DEVICES: str | None = None
|
|
CUDA_VERSION: version.Version
|
|
TORCH_VERSION: version.Version
|
|
|
|
environment_variables: dict[str, Callable[[], Any]] = {
|
|
# ================== Runtime Env Vars ==================
|
|
# used in distributed environment to determine the master address
|
|
"MASTER_ADDR": lambda: os.getenv("MASTER_ADDR", ""),
|
|
# used in distributed environment to manually set the communication port
|
|
"MASTER_PORT": lambda: (int(os.getenv("MASTER_PORT", "0")) if "MASTER_PORT" in os.environ else None),
|
|
# path to cudatoolkit home directory, under which should be bin, include,
|
|
# and lib directories.
|
|
"CUDA_HOME": lambda: os.environ.get("CUDA_HOME", None),
|
|
# local rank of the process in the distributed setting, used to determine
|
|
# the GPU device id
|
|
"LOCAL_RANK": lambda: int(os.environ.get("LOCAL_RANK", "0")),
|
|
# used to control the visible devices in the distributed setting
|
|
"CUDA_VISIBLE_DEVICES": lambda: os.environ.get("CUDA_VISIBLE_DEVICES", None),
|
|
}
|
|
|
|
|
|
def _is_hip():
|
|
has_rocm = torch.version.hip is not None
|
|
return has_rocm
|
|
|
|
|
|
def _is_cuda():
|
|
has_cuda = torch.version.cuda is not None
|
|
return has_cuda
|
|
|
|
|
|
def _is_musa():
|
|
try:
|
|
if hasattr(torch, "musa") and torch.musa.is_available():
|
|
return True
|
|
except ModuleNotFoundError:
|
|
return False
|
|
|
|
|
|
def _is_mps():
|
|
return torch.backends.mps.is_available()
|
|
|
|
|
|
def _is_npu():
|
|
try:
|
|
if hasattr(torch, "npu") and torch.npu.is_available():
|
|
return True
|
|
except ModuleNotFoundError:
|
|
return False
|
|
|
|
|
|
def get_device(local_rank: int) -> torch.device:
|
|
if _is_cuda() or _is_hip():
|
|
return torch.device("cuda", local_rank)
|
|
elif _is_musa():
|
|
return torch.device("musa", local_rank)
|
|
elif _is_mps():
|
|
return torch.device("mps")
|
|
elif _is_npu():
|
|
return torch.device("npu", local_rank)
|
|
else:
|
|
return torch.device("cpu")
|
|
|
|
|
|
def get_device_name() -> str:
|
|
if _is_cuda() or _is_hip():
|
|
return "cuda"
|
|
elif _is_musa():
|
|
return "musa"
|
|
elif _is_mps():
|
|
return "mps"
|
|
elif _is_npu():
|
|
return "npu"
|
|
else:
|
|
return "cpu"
|
|
|
|
|
|
def get_device_version():
|
|
if _is_hip():
|
|
hip_version = torch.version.hip
|
|
hip_version = hip_version.split("-")[0]
|
|
return hip_version
|
|
elif _is_cuda():
|
|
return torch.version.cuda
|
|
elif _is_musa():
|
|
return torch.version.musa
|
|
elif _is_mps():
|
|
return None
|
|
elif _is_npu():
|
|
return None
|
|
else:
|
|
raise NotImplementedError("No Accelerators(AMD/NV/MTT GPU, AMD MI instinct accelerators) available")
|
|
|
|
|
|
def get_torch_distributed_backend() -> str:
|
|
if _is_cuda() or _is_hip():
|
|
return "nccl"
|
|
elif _is_musa():
|
|
return "mccl"
|
|
elif _is_mps():
|
|
return "gloo"
|
|
elif _is_npu():
|
|
return "hccl"
|
|
else:
|
|
raise NotImplementedError("No Accelerators(AMD/NV/MTT GPU, AMD MI instinct accelerators) available")
|
|
|
|
|
|
variables: dict[str, Callable[[], Any]] = {
|
|
# ================== Other Vars ==================
|
|
# used in version checking
|
|
"CUDA_VERSION": lambda: version.parse(get_device_version() or "0.0"),
|
|
"TORCH_VERSION": lambda: version.parse(version.parse(torch.__version__).base_version),
|
|
}
|
|
|
|
|
|
def _setup_musa(environment_variables, variables):
|
|
musa = getattr(torch, "musa", None)
|
|
if musa is None:
|
|
return
|
|
try:
|
|
if musa.is_available():
|
|
environment_variables["MUSA_HOME"] = lambda: os.environ.get("MUSA_HOME", None)
|
|
environment_variables["MUSA_VISIBLE_DEVICES"] = lambda: os.environ.get("MUSA_VISIBLE_DEVICES", None)
|
|
musa_ver = getattr(getattr(torch, "version", None), "musa", None)
|
|
if musa_ver:
|
|
variables["MUSA_VERSION"] = lambda: version.parse(musa_ver)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
try:
|
|
_setup_musa(environment_variables, variables)
|
|
except (AttributeError, ModuleNotFoundError):
|
|
pass
|
|
|
|
|
|
class PackagesEnvChecker:
|
|
_instance = None
|
|
|
|
def __new__(cls):
|
|
if cls._instance is None:
|
|
cls._instance = super().__new__(cls)
|
|
cls._instance.initialize()
|
|
return cls._instance
|
|
|
|
def initialize(self):
|
|
packages_info = {}
|
|
packages_info["has_flash_attn"] = self.check_flash_attn(packages_info)
|
|
self.packages_info = packages_info
|
|
|
|
def check_flash_attn(self, packages_info):
|
|
if not torch.cuda.is_available():
|
|
return False
|
|
|
|
# Check if torch_npu is available
|
|
if _is_npu():
|
|
logger.info("`flash_attn` is not ready on torch_npu for now")
|
|
return False
|
|
|
|
if _is_musa():
|
|
logger.info("Flash Attention library is not supported on MUSA for the moment.")
|
|
return False
|
|
try:
|
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
gpu_name = torch.cuda.get_device_name(device)
|
|
if "Turing" in gpu_name or "Tesla" in gpu_name or "T4" in gpu_name:
|
|
return False
|
|
else:
|
|
from flash_attn import __version__
|
|
|
|
if __version__ < "2.6.0":
|
|
raise ImportError("install flash_attn >= 2.6.0")
|
|
return True
|
|
except ImportError:
|
|
if not packages_info.get("has_aiter", False):
|
|
logger.warning('Flash Attention library "flash_attn" not found, using pytorch attention implementation')
|
|
return False
|
|
|
|
def get_packages_info(self):
|
|
return self.packages_info
|
|
|
|
|
|
PACKAGES_CHECKER = PackagesEnvChecker()
|
|
|
|
|
|
def __getattr__(name):
|
|
# lazy evaluation of environment variables
|
|
if name in environment_variables:
|
|
return environment_variables[name]()
|
|
if name in variables:
|
|
return variables[name]()
|
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
|
|
|
|
def __dir__():
|
|
return list(environment_variables.keys())
|