diff --git a/bitsandbytes_windows/__init__.py b/bitsandbytes_windows/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/bitsandbytes_windows/cextension.py b/bitsandbytes_windows/cextension.py deleted file mode 100644 index c4f9fe8a..00000000 --- a/bitsandbytes_windows/cextension.py +++ /dev/null @@ -1,58 +0,0 @@ -import ctypes as ct -from pathlib import Path -from warnings import warn - -from dreambooth import shared -from .cuda_setup.main import evaluate_cuda_setup - - -class CUDALibrary_Singleton(object): - _instance = None - - def __init__(self): - raise RuntimeError("Call get_instance() instead") - - def initialize(self): - binary_name = evaluate_cuda_setup() - package_dir = Path(__file__).parent - binary_path = package_dir / binary_name - - if not binary_path.exists(): - print(f"CUDA SETUP: TODO: compile library for specific version: {binary_name}") - legacy_binary_name = "libbitsandbytes.so" - print(f"CUDA SETUP: Defaulting to {legacy_binary_name}...") - binary_path = package_dir / legacy_binary_name - if not binary_path.exists(): - print( - 'CUDA SETUP: CUDA detection failed. Either CUDA driver not installed, CUDA not installed, or you have multiple conflicting CUDA libraries!') - print( - 'CUDA SETUP: If you compiled from source, try again with `make CUDA_VERSION=DETECTED_CUDA_VERSION` for example, `make CUDA_VERSION=113`.') - raise Exception('CUDA SETUP: Setup Failed!') - # self.lib = ct.cdll.LoadLibrary(binary_path) - self.lib = ct.cdll.LoadLibrary(str(binary_path)) # $$$ - else: - print(f"CUDA SETUP: Loading binary {binary_path}...") - # self.lib = ct.cdll.LoadLibrary(binary_path) - self.lib = ct.cdll.LoadLibrary(str(binary_path)) # $$$ - - @classmethod - def get_instance(cls): - if cls._instance is None: - cls._instance = cls.__new__(cls) - cls._instance.initialize() - return cls._instance - - -if shared.device.type != "mps": - lib = CUDALibrary_Singleton.get_instance().lib - try: - lib.cadam32bit_g32 - lib.get_context.restype = ct.c_void_p - lib.get_cusparse.restype = ct.c_void_p - COMPILED_WITH_CUDA = True - except AttributeError: - warn( - "The installed version of bitsandbytes was compiled without GPU support. " - "8-bit optimizers and GPU quantization are unavailable." - ) - COMPILED_WITH_CUDA = False diff --git a/bitsandbytes_windows/libbitsandbytes_cpu.dll b/bitsandbytes_windows/libbitsandbytes_cpu.dll deleted file mode 100644 index b733af47..00000000 Binary files a/bitsandbytes_windows/libbitsandbytes_cpu.dll and /dev/null differ diff --git a/bitsandbytes_windows/libbitsandbytes_cudaall.dll b/bitsandbytes_windows/libbitsandbytes_cudaall.dll deleted file mode 100644 index 8a82a703..00000000 Binary files a/bitsandbytes_windows/libbitsandbytes_cudaall.dll and /dev/null differ diff --git a/bitsandbytes_windows/main.py b/bitsandbytes_windows/main.py deleted file mode 100644 index 3d513458..00000000 --- a/bitsandbytes_windows/main.py +++ /dev/null @@ -1,164 +0,0 @@ -""" -extract factors the build is dependent on: -[X] compute capability - [ ] TODO: Q - What if we have multiple GPUs of different makes? -- CUDA version -- Software: - - CPU-only: only CPU quantization functions (no optimizer, no matrix multipl) - - CuBLAS-LT: full-build 8-bit optimizer - - no CuBLAS-LT: no 8-bit matrix multiplication (`nomatmul`) - -evaluation: - - if paths faulty, return meaningful error - - else: - - determine CUDA version - - determine capabilities - - based on that set the default path -""" - -import ctypes -import os - -from .paths import determine_cuda_runtime_lib_path - - -def check_cuda_result(cuda, result_val): - # 3. Check for CUDA errors - if result_val != 0: - error_str = ctypes.c_char_p() - cuda.cuGetErrorString(result_val, ctypes.byref(error_str)) - print(f"CUDA exception! Error code: {error_str.value.decode()}") - - -def get_cuda_version(cuda, cudart_path): - # https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART____VERSION.html#group__CUDART____VERSION - try: - cudart = ctypes.CDLL(cudart_path) - except OSError: - # TODO: shouldn't we error or at least warn here? - print(f'ERROR: libcudart.so could not be read from path: {cudart_path}!') - return None - - version = ctypes.c_int() - check_cuda_result(cuda, cudart.cudaRuntimeGetVersion(ctypes.byref(version))) - version = int(version.value) - major = version // 1000 - minor = (version - (major * 1000)) // 10 - - if major < 11: - print( - 'CUDA SETUP: CUDA version lower than 11 are currenlty not supported for LLM.int8(). You will be only to use 8-bit optimizers and quantization routines!!') - - return f'{major}{minor}' - - -def get_cuda_lib_handle(): - # 1. find libcuda.so library (GPU driver) (/usr/lib) - try: - cuda = ctypes.CDLL("libcuda.so") - except OSError: - # TODO: shouldn't we error or at least warn here? - print( - 'CUDA SETUP: WARNING! libcuda.so not found! Do you have a CUDA driver installed? If you are on a cluster, make sure you are on a CUDA machine!') - return None - check_cuda_result(cuda, cuda.cuInit(0)) - - return cuda - - -def get_compute_capabilities(cuda): - """ - 1. find libcuda.so library (GPU driver) (/usr/lib) - init_device -> init variables -> call function by reference - 2. call extern C function to determine CC - (https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__DEVICE__DEPRECATED.html) - 3. Check for CUDA errors - https://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime-api - # bits taken from https://gist.github.com/f0k/63a664160d016a491b2cbea15913d549 - """ - - nGpus = ctypes.c_int() - cc_major = ctypes.c_int() - cc_minor = ctypes.c_int() - - device = ctypes.c_int() - - check_cuda_result(cuda, cuda.cuDeviceGetCount(ctypes.byref(nGpus))) - ccs = [] - for i in range(nGpus.value): - check_cuda_result(cuda, cuda.cuDeviceGet(ctypes.byref(device), i)) - ref_major = ctypes.byref(cc_major) - ref_minor = ctypes.byref(cc_minor) - # 2. call extern C function to determine CC - check_cuda_result( - cuda, cuda.cuDeviceComputeCapability(ref_major, ref_minor, device) - ) - ccs.append(f"{cc_major.value}.{cc_minor.value}") - - return ccs - - -# def get_compute_capability()-> Union[List[str, ...], None]: # FIXME: error -def get_compute_capability(cuda): - """ - Extracts the highest compute capbility from all available GPUs, as compute - capabilities are downwards compatible. If no GPUs are detected, it returns - None. - """ - ccs = get_compute_capabilities(cuda) - if ccs is not None: - # TODO: handle different compute capabilities; for now, take the max - return ccs[-1] - return None - - -def evaluate_cuda_setup(): - if os.name == "nt": - return "libbitsandbytes_cudaall.dll" # $$$ - - binary_name = "libbitsandbytes_cpu.so" - # if not torch.cuda.is_available(): - # print('No GPU detected. Loading CPU library...') - # return binary_name - - cudart_path = determine_cuda_runtime_lib_path() - if cudart_path is None: - print( - "WARNING: No libcudart.so found! Install CUDA or the cudatoolkit package (anaconda)!" - ) - return binary_name - - print(f"CUDA SETUP: CUDA runtime path found: {cudart_path}") - cuda = get_cuda_lib_handle() - cc = get_compute_capability(cuda) - print(f"CUDA SETUP: Highest compute capability among GPUs detected: {cc}") - cuda_version_string = get_cuda_version(cuda, cudart_path) - - if cc == '': - print( - "WARNING: No GPU detected! Check your CUDA paths. Processing to load CPU-only library..." - ) - return binary_name - - # 7.5 is the minimum CC vor cublaslt - has_cublaslt = cc in ["7.5", "8.0", "8.6"] - - # TODO: - # (1) CUDA missing cases (no CUDA installed by CUDA driver (nvidia-smi accessible) - # (2) Multiple CUDA versions installed - - # we use ls -l instead of nvcc to determine the cuda version - # since most installations will have the libcudart.so installed, but not the compiler - print(f'CUDA SETUP: Detected CUDA version {cuda_version_string}') - - def get_binary_name(): - """if not has_cublaslt (CC < 7.5), then we have to choose _nocublaslt.so""" - bin_base_name = "libbitsandbytes_cuda" - if has_cublaslt: - return f"{bin_base_name}{cuda_version_string}.so" - else: - return f"{bin_base_name}{cuda_version_string}_nocublaslt.so" - - binary_name = get_binary_name() - - return binary_name diff --git a/bitsandbytes_windows/paths.py b/bitsandbytes_windows/paths.py deleted file mode 100644 index 7634e5b5..00000000 --- a/bitsandbytes_windows/paths.py +++ /dev/null @@ -1,127 +0,0 @@ -import errno -import os -from pathlib import Path -from typing import Set, Union -from warnings import warn - -from .env_vars import get_potentially_lib_path_containing_env_vars - -CUDA_RUNTIME_LIB: str = "libcudart.so" if os.name != "nt" else "cudart64_110.dll" - - -def extract_candidate_paths(paths_list_candidate: str) -> Set[Path]: - return {Path(ld_path) for ld_path in paths_list_candidate.split(":") if ld_path} - - -def remove_non_existent_dirs(candidate_paths: Set[Path]) -> Set[Path]: - existent_directories: Set[Path] = set() - for path in candidate_paths: - try: - if path.exists(): - existent_directories.add(path) - except OSError as exc: - if exc.errno != errno.ENAMETOOLONG: - raise exc - - non_existent_directories: Set[Path] = candidate_paths - existent_directories - if non_existent_directories: - warn( - "WARNING: The following directories listed in your path were found to " - f"be non-existent: {non_existent_directories}" - ) - - return existent_directories - - -def get_cuda_runtime_lib_paths(candidate_paths: Set[Path]) -> Set[Path]: - return { - path / CUDA_RUNTIME_LIB - for path in candidate_paths - if (path / CUDA_RUNTIME_LIB).is_file() - } - - -def resolve_paths_list(paths_list_candidate: str) -> Set[Path]: - """ - Searches a given environmental var for the CUDA runtime library, - i.e. `libcudart.so`. - """ - return remove_non_existent_dirs(extract_candidate_paths(paths_list_candidate)) - - -def find_cuda_lib_in(paths_list_candidate: str) -> Set[Path]: - return get_cuda_runtime_lib_paths( - resolve_paths_list(paths_list_candidate) - ) - - -def warn_in_case_of_duplicates(results_paths: Set[Path]) -> None: - if len(results_paths) > 1: - warning_msg = ( - f"Found duplicate {CUDA_RUNTIME_LIB} files: {results_paths}.. " - "We'll flip a coin and try one of these, in order to fail forward.\n" - "Either way, this might cause trouble in the future:\n" - "If you get `CUDA error: invalid device function` errors, the above " - "might be the cause and the solution is to make sure only one " - f"{CUDA_RUNTIME_LIB} in the paths that we search based on your env." - ) - warn(warning_msg) - - -def determine_cuda_runtime_lib_path() -> Union[Path, None]: - """ - Searches for a cuda installations, in the following order of priority: - 1. active conda env - 2. LD_LIBRARY_PATH - 3. any other env vars, while ignoring those that - - are known to be unrelated (see `bnb.cuda_setup.env_vars.to_be_ignored`) - - don't contain the path separator `/` - - If multiple libraries are found in part 3, we optimistically try one, - while giving a warning message. - """ - candidate_env_vars = get_potentially_lib_path_containing_env_vars() - - if "CONDA_PREFIX" in candidate_env_vars: - conda_libs_path = Path(candidate_env_vars["CONDA_PREFIX"]) / "lib" - - conda_cuda_libs = find_cuda_lib_in(str(conda_libs_path)) - warn_in_case_of_duplicates(conda_cuda_libs) - - if conda_cuda_libs: - return next(iter(conda_cuda_libs)) - - warn( - f'{candidate_env_vars["CONDA_PREFIX"]} did not contain ' - f'{CUDA_RUNTIME_LIB} as expected! Searching further paths...' - ) - - if "LD_LIBRARY_PATH" in candidate_env_vars: - lib_ld_cuda_libs = find_cuda_lib_in(candidate_env_vars["LD_LIBRARY_PATH"]) - - if lib_ld_cuda_libs: - return next(iter(lib_ld_cuda_libs)) - warn_in_case_of_duplicates(lib_ld_cuda_libs) - - warn( - f'{candidate_env_vars["LD_LIBRARY_PATH"]} did not contain ' - f'{CUDA_RUNTIME_LIB} as expected! Searching further paths...' - ) - - remaining_candidate_env_vars = { - env_var: value for env_var, value in candidate_env_vars.items() - if env_var not in {"CONDA_PREFIX", "LD_LIBRARY_PATH"} - } - - cuda_runtime_libs = set() - for env_var, value in remaining_candidate_env_vars.items(): - cuda_runtime_libs.update(find_cuda_lib_in(value)) - - if len(cuda_runtime_libs) == 0: - print( - 'CUDA_SETUP: WARNING! libcudart.so not found in any environmental path. Searching /usr/local/cuda/lib64...') - cuda_runtime_libs.update(find_cuda_lib_in('/usr/local/cuda/lib64')) - - warn_in_case_of_duplicates(cuda_runtime_libs) - - return next(iter(cuda_runtime_libs)) if cuda_runtime_libs else None diff --git a/postinstall.py b/postinstall.py index 10664a67..3bf74a05 100644 --- a/postinstall.py +++ b/postinstall.py @@ -211,60 +211,18 @@ def check_bitsandbytes(): bitsandbytes_version = importlib_metadata.version("bitsandbytes") except: bitsandbytes_version = None - if os.name == "nt": - print("Checking bitsandbytes (Windows)") - venv_path = os.environ.get("VENV_DIR", None) - if ";" in venv_path: - venv_path = venv_path.split(";")[0] - print(f"Virtual environment path: {venv_path}") - # Check for the dll in venv/lib/site-packages/bitsandbytes/libbitsandbytes_cuda118.dll - # If it doesn't exist, append the requirement - if not venv_path: - print("Could not find the virtual environment path. Skipping bitsandbytes installation.") - else: - cuda_range = [f"1{str(x)}" for x in range(11, 22)] - dll_base = os.path.join(venv_path, "lib", "site-packages", "bitsandbytes", "libbitsandbytes_cuda") - win_dll = None - for cuda_ver in cuda_range: - dll_path = dll_base + cuda_ver + ".dll" - print(f"Checking for {dll_path}") - if os.path.exists(dll_path): - win_dll = dll_path - break - print(f"Found windows BNB DLL {win_dll}") - if win_dll is None or bitsandbytes_version is None or "0.41.2" not in bitsandbytes_version: - print("Can't find bitsandbytes CUDA dll. Installing bitsandbytes") - try: - pip_uninstall("bitsandbytes") - # Find any directories starting with ~ in the venv/lib/site-packages directory and delete them - for env_dir in os.listdir(os.path.join(venv_path, "lib", "site-packages")): - if env_dir.startswith("~"): - print(f"Deleting {env_dir}") - os.rmdir(os.path.join(venv_path, "lib", "site-packages", env_dir)) - except: - pass - print("Installing bitsandbytes") - try: - pip_install( - "--prefer-binary", - "https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.2.post2-py3-none-win_amd64.whl") - except Exception as e: - print("Bitsandbytes 0.41.2.post2 installation failed") - print("Some features such as 8bit optimizers will be unavailable") - print_bitsandbytes_installation_error(str(e)) - pass - else: - print("Checking bitsandbytes (Linux)") - if bitsandbytes_version is None or "0.41.2" not in bitsandbytes_version: - try: - print("Installing bitsandbytes") - pip_install("bitsandbytes==0.41.2.post2", "--prefer-binary") - except: - print("Bitsandbytes 0.41.2 installation failed") - print("Some features such as 8bit optimizers will be unavailable") - print("Install manually with") - print("'python -m pip install bitsandbytes==0.41.2.post2 --prefer-binary --force-install'") - pass + + print("Checking bitsandbytes (ALL!)") + if bitsandbytes_version is None or "0.43.0" not in bitsandbytes_version: + try: + print("Installing bitsandbytes") + pip_install("bitsandbytes==0.43.0", "--prefer-binary") + except: + print("Bitsandbytes 0.43.0 installation failed") + print("Some features such as 8bit optimizers will be unavailable") + print("Install manually with") + print("'python -m pip install bitsandbytes==0.43.0 --prefer-binary --force-install'") + pass @dataclass @@ -288,7 +246,7 @@ def check_versions(): ] if device == "cuda": - dependencies.append(Dependency(module="bitsandbytes", version="0.41.1.post2", required=False)) + dependencies.append(Dependency(module="bitsandbytes", version="0.43.0", required=False)) if device != "mps": dependencies.append(Dependency(module="xformers", version="0.0.21", required=False)) @@ -302,10 +260,12 @@ def check_versions(): installed_ver = importlib_metadata.version(module) if has_module else None if not installed_ver: + module_msg = "" if module != "xformers": launch_errors.append(f"{module} not installed.") + module_msg = "(Be sure to use the --xformers flag.)" - print(f"[!] {module} NOT installed.") + print(f"[!] {module} NOT installed.{module_msg}") continue required_version = dependency.version @@ -364,7 +324,7 @@ def print_bitsandbytes_installation_error(err): print("cd ../..") print("# WINDOWS ONLY: ") print( - "pip install --prefer-binary --force-reinstall https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.2.post2-py3-none-win_amd64.whl") + "pip install --prefer-binary --force-reinstall https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.43.0.post2-py3-none-win_amd64.whl") print("#######################################################################################################") @@ -407,7 +367,7 @@ def print_launch_errors(launch_errors): print("cd ../..") print("pip install -r ./extensions/sd_dreambooth_extension/requirements.txt") print( - "pip install --prefer-binary --force-reinstall https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.2.post2-py3-none-win_amd64.whl") + "pip install --prefer-binary --force-reinstall https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.43.0.post2-py3-none-win_amd64.whl") print("#######################################################################################################") diff --git a/preprocess/preprocess_utils.py b/preprocess/preprocess_utils.py index 5d4c203a..3bdef757 100644 --- a/preprocess/preprocess_utils.py +++ b/preprocess/preprocess_utils.py @@ -7,7 +7,8 @@ image_data = [] -def load_image_data(input_path: str, recurse: bool = False) -> List[Dict[str,str]]: + +def load_image_data(input_path: str, recurse: bool = False) -> List[Dict[str, str]]: if not os.path.exists(input_path): print(f"Input path {input_path} does not exist") return [] @@ -34,6 +35,7 @@ def load_image_data(input_path: str, recurse: bool = False) -> List[Dict[str,str image_data = output return output + def check_preprocess_path(input_path: str, recurse: bool = False) -> Tuple[gr.update, gr.update]: output_status = gr.update(visible=True) output_gallery = gr.update(visible=True) @@ -46,5 +48,6 @@ def check_preprocess_path(input_path: str, recurse: bool = False) -> Tuple[gr.up output_gallery = gr.update(visible=True, value=images) return output_status, output_gallery + def load_image_caption(evt: gr.SelectData): # SelectData is a subclass of EventData - return gr.update(value=f"You selected {evt.value} at {evt.index} from {evt.target}") \ No newline at end of file + return gr.update(value=f"You selected {evt.value} at {evt.index} from {evt.target}") diff --git a/requirements.txt b/requirements.txt index 0b8fa12c..8aaa4077 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +bitsandbytes>=0.43.0 accelerate>=0.21.0 dadaptation>=3.2 diffusers>=0.25.0 diff --git a/scripts/main.py b/scripts/main.py index e5ef5199..12f4fba4 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -59,6 +59,7 @@ refresh_symbol = "\U0001f504" # 🔄 delete_symbol = "\U0001F5D1" # 🗑️ update_symbol = "\U0001F51D" # 🠝 + log_parser = LogParser() show_advanced = True