Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| from __future__ import print_function | |
| # Unlike the rest of the PyTorch this file must be python2 compliant. | |
| # This script outputs relevant system environment info | |
| # Run it with `python collect_env.py`. | |
| import datetime | |
| import locale | |
| import re | |
| import subprocess | |
| import sys | |
| import os | |
| from collections import namedtuple | |
| try: | |
| import torch | |
| TORCH_AVAILABLE = True | |
| except (ImportError, NameError, AttributeError, OSError): | |
| TORCH_AVAILABLE = False | |
| # System Environment Information | |
| SystemEnv = namedtuple( | |
| "SystemEnv", | |
| [ | |
| "torch_version", | |
| "is_debug_build", | |
| "cuda_compiled_version", | |
| "gcc_version", | |
| "clang_version", | |
| "cmake_version", | |
| "os", | |
| "libc_version", | |
| "python_version", | |
| "python_platform", | |
| "is_cuda_available", | |
| "cuda_runtime_version", | |
| "nvidia_driver_version", | |
| "nvidia_gpu_models", | |
| "cudnn_version", | |
| "pip_version", # 'pip' or 'pip3' | |
| "pip_packages", | |
| "conda_packages", | |
| "hip_compiled_version", | |
| "hip_runtime_version", | |
| "miopen_runtime_version", | |
| "caching_allocator_config", | |
| "is_xnnpack_available", | |
| ], | |
| ) | |
| def run(command): | |
| """Returns (return-code, stdout, stderr)""" | |
| p = subprocess.Popen( | |
| command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True | |
| ) | |
| raw_output, raw_err = p.communicate() | |
| rc = p.returncode | |
| if get_platform() == "win32": | |
| enc = "oem" | |
| else: | |
| enc = locale.getpreferredencoding() | |
| output = raw_output.decode(enc) | |
| err = raw_err.decode(enc) | |
| return rc, output.strip(), err.strip() | |
| def run_and_read_all(run_lambda, command): | |
| """Runs command using run_lambda; reads and returns entire output if rc is 0""" | |
| rc, out, _ = run_lambda(command) | |
| if rc != 0: | |
| return None | |
| return out | |
| def run_and_parse_first_match(run_lambda, command, regex): | |
| """Runs command using run_lambda, returns the first regex match if it exists""" | |
| rc, out, _ = run_lambda(command) | |
| if rc != 0: | |
| return None | |
| match = re.search(regex, out) | |
| if match is None: | |
| return None | |
| return match.group(1) | |
| def run_and_return_first_line(run_lambda, command): | |
| """Runs command using run_lambda and returns first line if output is not empty""" | |
| rc, out, _ = run_lambda(command) | |
| if rc != 0: | |
| return None | |
| return out.split("\n")[0] | |
| def get_conda_packages(run_lambda): | |
| conda = os.environ.get("CONDA_EXE", "conda") | |
| out = run_and_read_all(run_lambda, "{} list".format(conda)) | |
| if out is None: | |
| return out | |
| return "\n".join( | |
| line | |
| for line in out.splitlines() | |
| if not line.startswith("#") | |
| and any( | |
| name in line | |
| for name in { | |
| "torch", | |
| "numpy", | |
| "cudatoolkit", | |
| "soumith", | |
| "mkl", | |
| "magma", | |
| "mkl", | |
| } | |
| ) | |
| ) | |
| def get_gcc_version(run_lambda): | |
| return run_and_parse_first_match(run_lambda, "gcc --version", r"gcc (.*)") | |
| def get_clang_version(run_lambda): | |
| return run_and_parse_first_match( | |
| run_lambda, "clang --version", r"clang version (.*)" | |
| ) | |
| def get_cmake_version(run_lambda): | |
| return run_and_parse_first_match(run_lambda, "cmake --version", r"cmake (.*)") | |
| def get_nvidia_driver_version(run_lambda): | |
| if get_platform() == "darwin": | |
| cmd = "kextstat | grep -i cuda" | |
| return run_and_parse_first_match( | |
| run_lambda, cmd, r"com[.]nvidia[.]CUDA [(](.*?)[)]" | |
| ) | |
| smi = get_nvidia_smi() | |
| return run_and_parse_first_match(run_lambda, smi, r"Driver Version: (.*?) ") | |
| def get_gpu_info(run_lambda): | |
| if get_platform() == "darwin" or ( | |
| TORCH_AVAILABLE | |
| and hasattr(torch.version, "hip") | |
| and torch.version.hip is not None | |
| ): | |
| if TORCH_AVAILABLE and torch.cuda.is_available(): | |
| return torch.cuda.get_device_name(None) | |
| return None | |
| smi = get_nvidia_smi() | |
| uuid_regex = re.compile(r" \(UUID: .+?\)") | |
| rc, out, _ = run_lambda(smi + " -L") | |
| if rc != 0: | |
| return None | |
| # Anonymize GPUs by removing their UUID | |
| return re.sub(uuid_regex, "", out) | |
| def get_running_cuda_version(run_lambda): | |
| return run_and_parse_first_match(run_lambda, "nvcc --version", r"release .+ V(.*)") | |
| def get_cudnn_version(run_lambda): | |
| """This will return a list of libcudnn.so; it's hard to tell which one is being used""" | |
| if get_platform() == "win32": | |
| system_root = os.environ.get("SYSTEMROOT", "C:\\Windows") | |
| cuda_path = os.environ.get("CUDA_PATH", "%CUDA_PATH%") | |
| where_cmd = os.path.join(system_root, "System32", "where") | |
| cudnn_cmd = '{} /R "{}\\bin" cudnn*.dll'.format(where_cmd, cuda_path) | |
| elif get_platform() == "darwin": | |
| # CUDA libraries and drivers can be found in /usr/local/cuda/. See | |
| # https://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#install | |
| # https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installmac | |
| # Use CUDNN_LIBRARY when cudnn library is installed elsewhere. | |
| cudnn_cmd = "ls /usr/local/cuda/lib/libcudnn*" | |
| else: | |
| cudnn_cmd = 'ldconfig -p | grep libcudnn | rev | cut -d" " -f1 | rev' | |
| rc, out, _ = run_lambda(cudnn_cmd) | |
| # find will return 1 if there are permission errors or if not found | |
| if len(out) == 0 or (rc != 1 and rc != 0): | |
| l = os.environ.get("CUDNN_LIBRARY") | |
| if l is not None and os.path.isfile(l): | |
| return os.path.realpath(l) | |
| return None | |
| files_set = set() | |
| for fn in out.split("\n"): | |
| fn = os.path.realpath(fn) # eliminate symbolic links | |
| if os.path.isfile(fn): | |
| files_set.add(fn) | |
| if not files_set: | |
| return None | |
| # Alphabetize the result because the order is non-deterministic otherwise | |
| files = list(sorted(files_set)) | |
| if len(files) == 1: | |
| return files[0] | |
| result = "\n".join(files) | |
| return "Probably one of the following:\n{}".format(result) | |
| def get_nvidia_smi(): | |
| # Note: nvidia-smi is currently available only on Windows and Linux | |
| smi = "nvidia-smi" | |
| if get_platform() == "win32": | |
| system_root = os.environ.get("SYSTEMROOT", "C:\\Windows") | |
| program_files_root = os.environ.get("PROGRAMFILES", "C:\\Program Files") | |
| legacy_path = os.path.join( | |
| program_files_root, "NVIDIA Corporation", "NVSMI", smi | |
| ) | |
| new_path = os.path.join(system_root, "System32", smi) | |
| smis = [new_path, legacy_path] | |
| for candidate_smi in smis: | |
| if os.path.exists(candidate_smi): | |
| smi = '"{}"'.format(candidate_smi) | |
| break | |
| return smi | |
| def get_platform(): | |
| if sys.platform.startswith("linux"): | |
| return "linux" | |
| elif sys.platform.startswith("win32"): | |
| return "win32" | |
| elif sys.platform.startswith("cygwin"): | |
| return "cygwin" | |
| elif sys.platform.startswith("darwin"): | |
| return "darwin" | |
| else: | |
| return sys.platform | |
| def get_mac_version(run_lambda): | |
| return run_and_parse_first_match(run_lambda, "sw_vers -productVersion", r"(.*)") | |
| def get_windows_version(run_lambda): | |
| system_root = os.environ.get("SYSTEMROOT", "C:\\Windows") | |
| wmic_cmd = os.path.join(system_root, "System32", "Wbem", "wmic") | |
| findstr_cmd = os.path.join(system_root, "System32", "findstr") | |
| return run_and_read_all( | |
| run_lambda, "{} os get Caption | {} /v Caption".format(wmic_cmd, findstr_cmd) | |
| ) | |
| def get_lsb_version(run_lambda): | |
| return run_and_parse_first_match( | |
| run_lambda, "lsb_release -a", r"Description:\t(.*)" | |
| ) | |
| def check_release_file(run_lambda): | |
| return run_and_parse_first_match( | |
| run_lambda, "cat /etc/*-release", r'PRETTY_NAME="(.*)"' | |
| ) | |
| def get_os(run_lambda): | |
| from platform import machine | |
| platform = get_platform() | |
| if platform == "win32" or platform == "cygwin": | |
| return get_windows_version(run_lambda) | |
| if platform == "darwin": | |
| version = get_mac_version(run_lambda) | |
| if version is None: | |
| return None | |
| return "macOS {} ({})".format(version, machine()) | |
| if platform == "linux": | |
| # Ubuntu/Debian based | |
| desc = get_lsb_version(run_lambda) | |
| if desc is not None: | |
| return "{} ({})".format(desc, machine()) | |
| # Try reading /etc/*-release | |
| desc = check_release_file(run_lambda) | |
| if desc is not None: | |
| return "{} ({})".format(desc, machine()) | |
| return "{} ({})".format(platform, machine()) | |
| # Unknown platform | |
| return platform | |
| def get_python_platform(): | |
| import platform | |
| return platform.platform() | |
| def get_libc_version(): | |
| import platform | |
| if get_platform() != "linux": | |
| return "N/A" | |
| return "-".join(platform.libc_ver()) | |
| def get_pip_packages(run_lambda): | |
| """Returns `pip list` output. Note: will also find conda-installed pytorch | |
| and numpy packages.""" | |
| # People generally have `pip` as `pip` or `pip3` | |
| # But here it is incoved as `python -mpip` | |
| def run_with_pip(pip): | |
| out = run_and_read_all(run_lambda, "{} list --format=freeze".format(pip)) | |
| return "\n".join( | |
| line | |
| for line in out.splitlines() | |
| if any( | |
| name in line | |
| for name in { | |
| "torch", | |
| "numpy", | |
| "mypy", | |
| } | |
| ) | |
| ) | |
| pip_version = "pip3" if sys.version[0] == "3" else "pip" | |
| out = run_with_pip(sys.executable + " -mpip") | |
| return pip_version, out | |
| def get_cachingallocator_config(): | |
| ca_config = os.environ.get("PYTORCH_CUDA_ALLOC_CONF", "") | |
| return ca_config | |
| def is_xnnpack_available(): | |
| if TORCH_AVAILABLE: | |
| import torch.backends.xnnpack | |
| return str(torch.backends.xnnpack.enabled) # type: ignore[attr-defined] | |
| else: | |
| return "N/A" | |
| def get_env_info(): | |
| run_lambda = run | |
| pip_version, pip_list_output = get_pip_packages(run_lambda) | |
| if TORCH_AVAILABLE: | |
| version_str = torch.__version__ | |
| debug_mode_str = str(torch.version.debug) | |
| cuda_available_str = str(torch.cuda.is_available()) | |
| cuda_version_str = torch.version.cuda | |
| if ( | |
| not hasattr(torch.version, "hip") or torch.version.hip is None | |
| ): # cuda version | |
| hip_compiled_version = hip_runtime_version = miopen_runtime_version = "N/A" | |
| else: # HIP version | |
| cfg = torch._C._show_config().split("\n") | |
| hip_runtime_version = [ | |
| s.rsplit(None, 1)[-1] for s in cfg if "HIP Runtime" in s | |
| ][0] | |
| miopen_runtime_version = [ | |
| s.rsplit(None, 1)[-1] for s in cfg if "MIOpen" in s | |
| ][0] | |
| cuda_version_str = "N/A" | |
| hip_compiled_version = torch.version.hip | |
| else: | |
| version_str = debug_mode_str = cuda_available_str = cuda_version_str = "N/A" | |
| hip_compiled_version = hip_runtime_version = miopen_runtime_version = "N/A" | |
| sys_version = sys.version.replace("\n", " ") | |
| return SystemEnv( | |
| torch_version=version_str, | |
| is_debug_build=debug_mode_str, | |
| python_version="{} ({}-bit runtime)".format( | |
| sys_version, sys.maxsize.bit_length() + 1 | |
| ), | |
| python_platform=get_python_platform(), | |
| is_cuda_available=cuda_available_str, | |
| cuda_compiled_version=cuda_version_str, | |
| cuda_runtime_version=get_running_cuda_version(run_lambda), | |
| nvidia_gpu_models=get_gpu_info(run_lambda), | |
| nvidia_driver_version=get_nvidia_driver_version(run_lambda), | |
| cudnn_version=get_cudnn_version(run_lambda), | |
| hip_compiled_version=hip_compiled_version, | |
| hip_runtime_version=hip_runtime_version, | |
| miopen_runtime_version=miopen_runtime_version, | |
| pip_version=pip_version, | |
| pip_packages=pip_list_output, | |
| conda_packages=get_conda_packages(run_lambda), | |
| os=get_os(run_lambda), | |
| libc_version=get_libc_version(), | |
| gcc_version=get_gcc_version(run_lambda), | |
| clang_version=get_clang_version(run_lambda), | |
| cmake_version=get_cmake_version(run_lambda), | |
| caching_allocator_config=get_cachingallocator_config(), | |
| is_xnnpack_available=is_xnnpack_available(), | |
| ) | |
| env_info_fmt = """ | |
| PyTorch version: {torch_version} | |
| Is debug build: {is_debug_build} | |
| CUDA used to build PyTorch: {cuda_compiled_version} | |
| ROCM used to build PyTorch: {hip_compiled_version} | |
| OS: {os} | |
| GCC version: {gcc_version} | |
| Clang version: {clang_version} | |
| CMake version: {cmake_version} | |
| Libc version: {libc_version} | |
| Python version: {python_version} | |
| Python platform: {python_platform} | |
| Is CUDA available: {is_cuda_available} | |
| CUDA runtime version: {cuda_runtime_version} | |
| GPU models and configuration: {nvidia_gpu_models} | |
| Nvidia driver version: {nvidia_driver_version} | |
| cuDNN version: {cudnn_version} | |
| HIP runtime version: {hip_runtime_version} | |
| MIOpen runtime version: {miopen_runtime_version} | |
| Is XNNPACK available: {is_xnnpack_available} | |
| Versions of relevant libraries: | |
| {pip_packages} | |
| {conda_packages} | |
| """.strip() | |
| def pretty_str(envinfo): | |
| def replace_nones(dct, replacement="Could not collect"): | |
| for key in dct.keys(): | |
| if dct[key] is not None: | |
| continue | |
| dct[key] = replacement | |
| return dct | |
| def replace_bools(dct, true="Yes", false="No"): | |
| for key in dct.keys(): | |
| if dct[key] is True: | |
| dct[key] = true | |
| elif dct[key] is False: | |
| dct[key] = false | |
| return dct | |
| def prepend(text, tag="[prepend]"): | |
| lines = text.split("\n") | |
| updated_lines = [tag + line for line in lines] | |
| return "\n".join(updated_lines) | |
| def replace_if_empty(text, replacement="No relevant packages"): | |
| if text is not None and len(text) == 0: | |
| return replacement | |
| return text | |
| def maybe_start_on_next_line(string): | |
| # If `string` is multiline, prepend a \n to it. | |
| if string is not None and len(string.split("\n")) > 1: | |
| return "\n{}\n".format(string) | |
| return string | |
| mutable_dict = envinfo._asdict() | |
| # If nvidia_gpu_models is multiline, start on the next line | |
| mutable_dict["nvidia_gpu_models"] = maybe_start_on_next_line( | |
| envinfo.nvidia_gpu_models | |
| ) | |
| # If the machine doesn't have CUDA, report some fields as 'No CUDA' | |
| dynamic_cuda_fields = [ | |
| "cuda_runtime_version", | |
| "nvidia_gpu_models", | |
| "nvidia_driver_version", | |
| ] | |
| all_cuda_fields = dynamic_cuda_fields + ["cudnn_version"] | |
| all_dynamic_cuda_fields_missing = all( | |
| mutable_dict[field] is None for field in dynamic_cuda_fields | |
| ) | |
| if ( | |
| TORCH_AVAILABLE | |
| and not torch.cuda.is_available() | |
| and all_dynamic_cuda_fields_missing | |
| ): | |
| for field in all_cuda_fields: | |
| mutable_dict[field] = "No CUDA" | |
| if envinfo.cuda_compiled_version is None: | |
| mutable_dict["cuda_compiled_version"] = "None" | |
| # Replace True with Yes, False with No | |
| mutable_dict = replace_bools(mutable_dict) | |
| # Replace all None objects with 'Could not collect' | |
| mutable_dict = replace_nones(mutable_dict) | |
| # If either of these are '', replace with 'No relevant packages' | |
| mutable_dict["pip_packages"] = replace_if_empty(mutable_dict["pip_packages"]) | |
| mutable_dict["conda_packages"] = replace_if_empty(mutable_dict["conda_packages"]) | |
| # Tag conda and pip packages with a prefix | |
| # If they were previously None, they'll show up as ie '[conda] Could not collect' | |
| if mutable_dict["pip_packages"]: | |
| mutable_dict["pip_packages"] = prepend( | |
| mutable_dict["pip_packages"], "[{}] ".format(envinfo.pip_version) | |
| ) | |
| if mutable_dict["conda_packages"]: | |
| mutable_dict["conda_packages"] = prepend( | |
| mutable_dict["conda_packages"], "[conda] " | |
| ) | |
| return env_info_fmt.format(**mutable_dict) | |
| def get_pretty_env_info(): | |
| return pretty_str(get_env_info()) | |
| def main(): | |
| print("Collecting environment information...") | |
| output = get_pretty_env_info() | |
| print(output) | |
| if ( | |
| TORCH_AVAILABLE | |
| and hasattr(torch, "utils") | |
| and hasattr(torch.utils, "_crash_handler") | |
| ): | |
| minidump_dir = torch.utils._crash_handler.DEFAULT_MINIDUMP_DIR | |
| if sys.platform == "linux" and os.path.exists(minidump_dir): | |
| dumps = [ | |
| os.path.join(minidump_dir, dump) for dump in os.listdir(minidump_dir) | |
| ] | |
| latest = max(dumps, key=os.path.getctime) | |
| ctime = os.path.getctime(latest) | |
| creation_time = datetime.datetime.fromtimestamp(ctime).strftime( | |
| "%Y-%m-%d %H:%M:%S" | |
| ) | |
| msg = ( | |
| "\n*** Detected a minidump at {} created on {}, ".format( | |
| latest, creation_time | |
| ) | |
| + "if this is related to your bug please include it when you file a report ***" | |
| ) | |
| print(msg, file=sys.stderr) | |
| if __name__ == "__main__": | |
| main() | |