From fefbe2b1754a0b3943a01f6553093e440e021810 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 23 Nov 2024 01:10:12 +0100 Subject: [PATCH 01/22] Create update-runtime-directml.cmd --- update-runtime-directml.cmd | 86 +++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 update-runtime-directml.cmd diff --git a/update-runtime-directml.cmd b/update-runtime-directml.cmd new file mode 100644 index 00000000..331b1bbd --- /dev/null +++ b/update-runtime-directml.cmd @@ -0,0 +1,86 @@ +@echo off +cd /d "%~dp0" + +SET MAMBA_ROOT_PREFIX=%~dp0conda +echo %MAMBA_ROOT_PREFIX% + +if exist "%MAMBA_ROOT_PREFIX%\condabin\micromamba.bat" ( + echo Deleting micromamba.exe as its out of date + del micromamba.exe + if errorlevel 1 ( + echo Error: Failed to delete micromamba.exe. Please delete it manually. + exit /b 1 + ) + echo Deleting the conda directory as its out of date + rmdir /s /q conda + if errorlevel 1 ( + echo Error: Failed to delete the conda directory. Please delete it manually. + exit /b 1 + ) +) + +:Check if micromamba is already installed +if exist micromamba.exe goto Isolation + curl.exe -L -o micromamba.exe https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-win-64 + + +:Isolation +SET CONDA_SHLVL= +SET PYTHONNOUSERSITE=1 +SET PYTHONPATH= +echo %MAMBA_ROOT_PREFIX% + + + +setlocal EnableDelayedExpansion +for %%a in (%*) do ( + if /I "%%a"=="--hordelib" ( + set hordelib=true + ) else ( + set hordelib= + ) + if /I "%%a"=="--scribe" ( + set scribe=true + ) else ( + set scribe= + ) +) +endlocal + +if defined scribe ( + SET CONDA_ENVIRONMENT_FILE=environment_scribe.yaml + +) else ( + SET CONDA_ENVIRONMENT_FILE=environment.rocm.yaml +) + +Reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v "LongPathsEnabled" /t REG_DWORD /d "1" /f 2>nul +:We do this twice the first time to workaround a conda bug where pip is not installed correctly the first time - Henk +IF EXIST CONDA GOTO WORKAROUND_END +.\micromamba.exe create --no-shortcuts -r conda -n windows -f %CONDA_ENVIRONMENT_FILE% -y +:WORKAROUND_END +.\micromamba.exe create --no-shortcuts -r conda -n windows -f %CONDA_ENVIRONMENT_FILE% -y + +REM Check if hordelib argument is defined + +micromamba.exe shell hook -s cmd.exe %MAMBA_ROOT_PREFIX% -v +call "%MAMBA_ROOT_PREFIX%\condabin\mamba_hook.bat" +call "%MAMBA_ROOT_PREFIX%\condabin\mamba.bat" activate windows + +python -s -m pip install torch-directml torchvision==0.19.1 + +if defined hordelib ( + python -s -m pip uninstall -y hordelib horde_engine horde_model_reference + python -s -m pip install horde_engine horde_model_reference +) else ( + if defined scribe ( + python -s -m pip install -r requirements-scribe.txt + ) else ( + python -s -m pip install -r requirements.directml.txt + ) +) +call deactivate + +echo If there are no errors above everything should be correctly installed (If not, try deleting the folder /conda/envs/ and try again). + +pause From 6d35a690d7f2846ee5ac6a6b70d2608a81a5920f Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 23 Nov 2024 01:11:31 +0100 Subject: [PATCH 02/22] Create requirements.directml.txt --- requirements.directml.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 requirements.directml.txt diff --git a/requirements.directml.txt b/requirements.directml.txt new file mode 100644 index 00000000..f8442c9c --- /dev/null +++ b/requirements.directml.txt @@ -0,0 +1,24 @@ +torch-directml +qrcode==7.4.2 # >8 breaks horde-engine 2.18.1 via the qr code generation nodes + +certifi # Required for SSL cert resolution + +horde_sdk~=0.15.1 +horde_safety~=0.2.3 +horde_engine~=2.18.1 +horde_model_reference>=0.9.1 + +python-dotenv +ruamel.yaml +semver +wheel + +python-Levenshtein + +pydantic>=2.9.2 +typing_extensions +requests +StrEnum +loguru + +babel From 36b1a661db6168bf5b20940bf87d43c0acc75a1f Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 23 Nov 2024 01:00:06 +0100 Subject: [PATCH 03/22] try directml --- horde_worker_regen/process_management/worker_entry_points.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/horde_worker_regen/process_management/worker_entry_points.py b/horde_worker_regen/process_management/worker_entry_points.py index c7e77941..f653b397 100644 --- a/horde_worker_regen/process_management/worker_entry_points.py +++ b/horde_worker_regen/process_management/worker_entry_points.py @@ -59,7 +59,7 @@ def start_inference_process( f"and amd_gpu={amd_gpu}", ) - extra_comfyui_args = ["--disable-smart-memory"] + extra_comfyui_args = ["--disable-smart-memory --directml"] if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") @@ -148,7 +148,7 @@ def start_safety_process( logger.debug(f"Initialising hordelib with process_id={process_id} and high_memory_mode={high_memory_mode}") - extra_comfyui_args = ["--disable-smart-memory"] + extra_comfyui_args = ["--disable-smart-memory --directml"] if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") From 8c8246de25c2f6525690f63c6c2b3defb1ccb5dd Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 23 Nov 2024 01:39:45 +0100 Subject: [PATCH 04/22] directml init --- horde_worker_regen/download_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/horde_worker_regen/download_models.py b/horde_worker_regen/download_models.py index 51432149..7186c6df 100644 --- a/horde_worker_regen/download_models.py +++ b/horde_worker_regen/download_models.py @@ -55,7 +55,7 @@ def download_all_models( _ = get_interrogator_no_blip() del _ - hordelib.initialise() + hordelib.initialise(extra_comfyui_args="--directml") from hordelib.shared_model_manager import SharedModelManager SharedModelManager.load_model_managers() From c759c89189e7bfd3fd6bbdd4b25b13c039b5fec8 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 23 Nov 2024 01:42:13 +0100 Subject: [PATCH 05/22] array --- horde_worker_regen/download_models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/horde_worker_regen/download_models.py b/horde_worker_regen/download_models.py index 7186c6df..219c4769 100644 --- a/horde_worker_regen/download_models.py +++ b/horde_worker_regen/download_models.py @@ -55,7 +55,8 @@ def download_all_models( _ = get_interrogator_no_blip() del _ - hordelib.initialise(extra_comfyui_args="--directml") + extra_comfyui_args = ["--disable-smart-memory --directml"] + hordelib.initialise(extra_comfyui_args=extra_comfyui_args) from hordelib.shared_model_manager import SharedModelManager SharedModelManager.load_model_managers() From 30d275ad4f94004712ab3ac08922a826d596b17f Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 23 Nov 2024 01:46:54 +0100 Subject: [PATCH 06/22] pass directml --- horde_worker_regen/download_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/horde_worker_regen/download_models.py b/horde_worker_regen/download_models.py index 219c4769..42d77a2b 100644 --- a/horde_worker_regen/download_models.py +++ b/horde_worker_regen/download_models.py @@ -55,7 +55,7 @@ def download_all_models( _ = get_interrogator_no_blip() del _ - extra_comfyui_args = ["--disable-smart-memory --directml"] + extra_comfyui_args = ["--directml=0"] hordelib.initialise(extra_comfyui_args=extra_comfyui_args) from hordelib.shared_model_manager import SharedModelManager From 04a570c982b37b26d7c7f3f6fe96df552c7a9d33 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 23 Nov 2024 12:36:31 +0100 Subject: [PATCH 07/22] pass directml --- horde_worker_regen/process_management/worker_entry_points.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/horde_worker_regen/process_management/worker_entry_points.py b/horde_worker_regen/process_management/worker_entry_points.py index f653b397..1e23e97b 100644 --- a/horde_worker_regen/process_management/worker_entry_points.py +++ b/horde_worker_regen/process_management/worker_entry_points.py @@ -59,7 +59,7 @@ def start_inference_process( f"and amd_gpu={amd_gpu}", ) - extra_comfyui_args = ["--disable-smart-memory --directml"] + extra_comfyui_args = ["--disable-smart-memory", "--directml=0"] if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") @@ -148,7 +148,7 @@ def start_safety_process( logger.debug(f"Initialising hordelib with process_id={process_id} and high_memory_mode={high_memory_mode}") - extra_comfyui_args = ["--disable-smart-memory --directml"] + extra_comfyui_args = ["--disable-smart-memory", "--directml=0"] if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") From 15dc1578201043856c2af203b168b5ab58c0e941 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:57:05 +0100 Subject: [PATCH 08/22] add --directml to download --- download_models.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/download_models.py b/download_models.py index ec611b7b..8d4a1e48 100644 --- a/download_models.py +++ b/download_models.py @@ -17,6 +17,12 @@ default=False, help="Load the config only from environment variables. This is useful for running the worker in a container.", ) + parser.add_argument( + "--directml", + type=int, + default=None, + help="Enable directml and specify device to use.", + ) args = parser.parse_args() @@ -25,4 +31,5 @@ download_all_models( purge_unused_loras=args.purge_unused_loras, load_config_from_env_vars=args.load_config_from_env_vars, + directml=args.directml, ) From 42667aad301358e028932444a43e62259b7c423f Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:57:13 +0100 Subject: [PATCH 09/22] add --directml to download --- horde_worker_regen/download_models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/horde_worker_regen/download_models.py b/horde_worker_regen/download_models.py index 42d77a2b..6e60f1fe 100644 --- a/horde_worker_regen/download_models.py +++ b/horde_worker_regen/download_models.py @@ -5,6 +5,7 @@ def download_all_models( *, load_config_from_env_vars: bool = False, purge_unused_loras: bool = False, + directml: int = None, ) -> None: """Download all models specified in the config file.""" from horde_worker_regen.load_env_vars import load_env_vars_from_config @@ -55,7 +56,10 @@ def download_all_models( _ = get_interrogator_no_blip() del _ - extra_comfyui_args = ["--directml=0"] + extra_comfyui_args = [] + if directml: + extra_comfyui_args.append(f"--directml={directml}") + hordelib.initialise(extra_comfyui_args=extra_comfyui_args) from hordelib.shared_model_manager import SharedModelManager From 97a20958327025f7001170b10e68dc8ba09176c5 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:57:49 +0100 Subject: [PATCH 10/22] add --directml to worker --- horde_worker_regen/run_worker.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/horde_worker_regen/run_worker.py b/horde_worker_regen/run_worker.py index 8f48af80..412ab80d 100644 --- a/horde_worker_regen/run_worker.py +++ b/horde_worker_regen/run_worker.py @@ -18,7 +18,7 @@ from loguru import logger -def main(ctx: BaseContext, load_from_env_vars: bool = False, *, amd_gpu: bool = False) -> None: +def main(ctx: BaseContext, load_from_env_vars: bool = False, *, amd_gpu: bool = False, directml: int = None) -> None: """Check for a valid config and start the driver ('main') process for the reGen worker.""" from horde_model_reference.model_reference_manager import ModelReferenceManager from pydantic import ValidationError @@ -98,6 +98,7 @@ def ensure_model_db_downloaded() -> ModelReferenceManager: bridge_data=bridge_data, horde_model_reference_manager=horde_model_reference_manager, amd_gpu=amd_gpu, + directml=directml, ) @@ -165,6 +166,12 @@ def init() -> None: default=None, help="Override the worker name from the config file, for running multiple workers on one machine", ) + parser.add_argument( + "--directml", + type=int, + default=None, + help="Enable directml and specify device to use.", + ) args = parser.parse_args() @@ -206,7 +213,7 @@ def init() -> None: # We only need to download the legacy DBs once, so we do it here instead of in the worker processes - main(multiprocessing.get_context("spawn"), args.load_config_from_env_vars, amd_gpu=args.amd) + main(multiprocessing.get_context("spawn"), args.load_config_from_env_vars, amd_gpu=args.amd, directml=directml) if __name__ == "__main__": From 702e55ebc9b8c36148471dfe2cb9f9110b21561e Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:58:20 +0100 Subject: [PATCH 11/22] add --directml to worker --- horde_worker_regen/process_management/main_entry_point.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/horde_worker_regen/process_management/main_entry_point.py b/horde_worker_regen/process_management/main_entry_point.py index 04e539f5..25bf1fdf 100644 --- a/horde_worker_regen/process_management/main_entry_point.py +++ b/horde_worker_regen/process_management/main_entry_point.py @@ -12,6 +12,7 @@ def start_working( horde_model_reference_manager: ModelReferenceManager, *, amd_gpu: bool = False, + directml: int = None, ) -> None: """Create and start process manager.""" process_manager = HordeWorkerProcessManager( @@ -19,6 +20,7 @@ def start_working( bridge_data=bridge_data, horde_model_reference_manager=horde_model_reference_manager, amd_gpu=amd_gpu, + directml=directml, ) process_manager.start() From 0f221ef0c1b30ceaa7a9827d1b9b86a695ae9bf9 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:58:30 +0100 Subject: [PATCH 12/22] add --directml to worker --- horde_worker_regen/process_management/process_manager.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/horde_worker_regen/process_management/process_manager.py b/horde_worker_regen/process_management/process_manager.py index 0c0169f6..cdc1590a 100644 --- a/horde_worker_regen/process_management/process_manager.py +++ b/horde_worker_regen/process_management/process_manager.py @@ -1076,6 +1076,9 @@ def num_total_processes(self) -> int: _amd_gpu: bool """Whether or not the GPU is an AMD GPU.""" + _directml: int + """ID of the potential directml device.""" + def __init__( self, *, @@ -1087,6 +1090,7 @@ def __init__( max_safety_processes: int = 1, max_download_processes: int = 1, amd_gpu: bool = False, + directml: int = None, ) -> None: """Initialise the process manager. @@ -1103,6 +1107,7 @@ def __init__( max_download_processes (int, optional): The maximum number of download processes that can run at once. \ Defaults to 1. amd_gpu (bool, optional): Whether or not the GPU is an AMD GPU. Defaults to False. + directml (int, optional): ID of the potential directml device. Defaults to None. """ self.session_start_time = time.time() @@ -1124,6 +1129,7 @@ def __init__( self._lru = LRUCache(self.max_inference_processes) self._amd_gpu = amd_gpu + self._directml = directml # If there is only one model to load and only one inference process, then we can only run one job at a time # and there is no point in having more than one inference process @@ -1374,6 +1380,7 @@ def start_safety_processes(self) -> None: kwargs={ "high_memory_mode": self.bridge_data.high_memory_mode, "amd_gpu": self._amd_gpu, + "directml": self._directml, }, ) @@ -1436,6 +1443,7 @@ def _start_inference_process(self, pid: int) -> HordeProcessInfo: "very_high_memory_mode": self.bridge_data.very_high_memory_mode, "high_memory_mode": self.bridge_data.high_memory_mode, "amd_gpu": self._amd_gpu, + "directml": self._directml, }, ) process.start() From 528a76e36468fdeed93b9ff9cec9febcd6407a13 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:58:40 +0100 Subject: [PATCH 13/22] add --directml to worker --- .../process_management/worker_entry_points.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/horde_worker_regen/process_management/worker_entry_points.py b/horde_worker_regen/process_management/worker_entry_points.py index 1e23e97b..1d50f862 100644 --- a/horde_worker_regen/process_management/worker_entry_points.py +++ b/horde_worker_regen/process_management/worker_entry_points.py @@ -24,6 +24,7 @@ def start_inference_process( high_memory_mode: bool = False, very_high_memory_mode: bool = False, amd_gpu: bool = False, + directml: int = None, ) -> None: """Start an inference process. @@ -59,11 +60,14 @@ def start_inference_process( f"and amd_gpu={amd_gpu}", ) - extra_comfyui_args = ["--disable-smart-memory", "--directml=0"] + extra_comfyui_args = ["--disable-smart-memory"] if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") + if directml: + extra_comfyui_args.append(f"--directml={directml}") + models_not_to_force_load = ["flux"] if very_high_memory_mode: @@ -120,6 +124,7 @@ def start_safety_process( *, high_memory_mode: bool = False, amd_gpu: bool = False, + directml: int = None, ) -> None: """Start a safety process. @@ -148,11 +153,14 @@ def start_safety_process( logger.debug(f"Initialising hordelib with process_id={process_id} and high_memory_mode={high_memory_mode}") - extra_comfyui_args = ["--disable-smart-memory", "--directml=0"] + extra_comfyui_args = ["--disable-smart-memory"] if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") + if directml: + extra_comfyui_args.append(f"--directml={directml}") + with logger.catch(reraise=True): hordelib.initialise( setup_logging=None, From a28effbe4322b3eb2930e8912b9f9c5187e6ee29 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:03:19 +0100 Subject: [PATCH 14/22] Create horde-bridge-directml.cmd --- horde-bridge-directml.cmd | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 horde-bridge-directml.cmd diff --git a/horde-bridge-directml.cmd b/horde-bridge-directml.cmd new file mode 100644 index 00000000..7cb987f1 --- /dev/null +++ b/horde-bridge-directml.cmd @@ -0,0 +1,35 @@ +@echo off +cd /d %~dp0 + +: This first call to runtime activates the environment for the rest of the script +call runtime python -s -m pip -V + +call python -s -m pip uninstall hordelib +call python -s -m pip install horde_sdk~=0.16.4 horde_model_reference~=0.9.1 horde_engine~=2.18.1 horde_safety~=0.2.3 -U + +if %ERRORLEVEL% NEQ 0 ( + echo "Please run update-runtime.cmd." + GOTO END +) + +call python -s -m pip check +if %ERRORLEVEL% NEQ 0 ( + echo "Please run update-runtime.cmd." + GOTO END +) + +:DOWNLOAD +call python -s download_models.py --directml=0 +if %ERRORLEVEL% NEQ 0 GOTO ABORT +echo "Model Download OK. Starting worker..." +call python -s run_worker.py --directml=0 %* + +GOTO END + +:ABORT +echo "download_models.py exited with error code. Aborting" + +:END +call micromamba deactivate >nul +call deactivate >nul +pause From edc99a04ae35726b8bf255fafad3166605e2bdf1 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:10:04 +0100 Subject: [PATCH 15/22] PEP 484 compliance --- horde_worker_regen/download_models.py | 2 +- horde_worker_regen/process_management/main_entry_point.py | 2 +- horde_worker_regen/process_management/process_manager.py | 2 +- horde_worker_regen/process_management/worker_entry_points.py | 4 ++-- horde_worker_regen/run_worker.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/horde_worker_regen/download_models.py b/horde_worker_regen/download_models.py index 6e60f1fe..b4bdf1da 100644 --- a/horde_worker_regen/download_models.py +++ b/horde_worker_regen/download_models.py @@ -5,7 +5,7 @@ def download_all_models( *, load_config_from_env_vars: bool = False, purge_unused_loras: bool = False, - directml: int = None, + directml: int | None = None, ) -> None: """Download all models specified in the config file.""" from horde_worker_regen.load_env_vars import load_env_vars_from_config diff --git a/horde_worker_regen/process_management/main_entry_point.py b/horde_worker_regen/process_management/main_entry_point.py index 25bf1fdf..47e14ded 100644 --- a/horde_worker_regen/process_management/main_entry_point.py +++ b/horde_worker_regen/process_management/main_entry_point.py @@ -12,7 +12,7 @@ def start_working( horde_model_reference_manager: ModelReferenceManager, *, amd_gpu: bool = False, - directml: int = None, + directml: int | None = None, ) -> None: """Create and start process manager.""" process_manager = HordeWorkerProcessManager( diff --git a/horde_worker_regen/process_management/process_manager.py b/horde_worker_regen/process_management/process_manager.py index cdc1590a..af32f86e 100644 --- a/horde_worker_regen/process_management/process_manager.py +++ b/horde_worker_regen/process_management/process_manager.py @@ -1090,7 +1090,7 @@ def __init__( max_safety_processes: int = 1, max_download_processes: int = 1, amd_gpu: bool = False, - directml: int = None, + directml: int | None = None, ) -> None: """Initialise the process manager. diff --git a/horde_worker_regen/process_management/worker_entry_points.py b/horde_worker_regen/process_management/worker_entry_points.py index 1d50f862..f51e6e0e 100644 --- a/horde_worker_regen/process_management/worker_entry_points.py +++ b/horde_worker_regen/process_management/worker_entry_points.py @@ -24,7 +24,7 @@ def start_inference_process( high_memory_mode: bool = False, very_high_memory_mode: bool = False, amd_gpu: bool = False, - directml: int = None, + directml: int | None = None, ) -> None: """Start an inference process. @@ -124,7 +124,7 @@ def start_safety_process( *, high_memory_mode: bool = False, amd_gpu: bool = False, - directml: int = None, + directml: int | None = None, ) -> None: """Start a safety process. diff --git a/horde_worker_regen/run_worker.py b/horde_worker_regen/run_worker.py index 412ab80d..b2940543 100644 --- a/horde_worker_regen/run_worker.py +++ b/horde_worker_regen/run_worker.py @@ -18,7 +18,7 @@ from loguru import logger -def main(ctx: BaseContext, load_from_env_vars: bool = False, *, amd_gpu: bool = False, directml: int = None) -> None: +def main(ctx: BaseContext, load_from_env_vars: bool = False, *, amd_gpu: bool = False, directml: int | None = None) -> None: """Check for a valid config and start the driver ('main') process for the reGen worker.""" from horde_model_reference.model_reference_manager import ModelReferenceManager from pydantic import ValidationError From 20e35f81b0d81fee6bd87097207bee46beb955f1 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:17:18 +0100 Subject: [PATCH 16/22] fix syntax --- horde_worker_regen/run_worker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/horde_worker_regen/run_worker.py b/horde_worker_regen/run_worker.py index b2940543..51ca635d 100644 --- a/horde_worker_regen/run_worker.py +++ b/horde_worker_regen/run_worker.py @@ -18,7 +18,7 @@ from loguru import logger -def main(ctx: BaseContext, load_from_env_vars: bool = False, *, amd_gpu: bool = False, directml: int | None = None) -> None: +def main(ctx: BaseContext, load_from_env_vars: bool = False, *, amd_gpu: bool = False, directml: int | None = None,) -> None: """Check for a valid config and start the driver ('main') process for the reGen worker.""" from horde_model_reference.model_reference_manager import ModelReferenceManager from pydantic import ValidationError @@ -213,7 +213,7 @@ def init() -> None: # We only need to download the legacy DBs once, so we do it here instead of in the worker processes - main(multiprocessing.get_context("spawn"), args.load_config_from_env_vars, amd_gpu=args.amd, directml=directml) + main(multiprocessing.get_context("spawn"), args.load_config_from_env_vars, amd_gpu=args.amd, directml=args.directml,) if __name__ == "__main__": From da7ad13ebd3b5a7f9e8012c783e0357f09f32025 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:30:54 +0100 Subject: [PATCH 17/22] correct type --- horde_worker_regen/process_management/process_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/horde_worker_regen/process_management/process_manager.py b/horde_worker_regen/process_management/process_manager.py index af32f86e..6c84fcb4 100644 --- a/horde_worker_regen/process_management/process_manager.py +++ b/horde_worker_regen/process_management/process_manager.py @@ -1076,7 +1076,7 @@ def num_total_processes(self) -> int: _amd_gpu: bool """Whether or not the GPU is an AMD GPU.""" - _directml: int + _directml: int | None """ID of the potential directml device.""" def __init__( From d57b77745714526bd4ebe468698cac2eeee08465 Mon Sep 17 00:00:00 2001 From: HPPinata <83947761+HPPinata@users.noreply.github.com> Date: Sat, 30 Nov 2024 11:01:36 +0100 Subject: [PATCH 18/22] correct check --- horde_worker_regen/download_models.py | 2 +- horde_worker_regen/process_management/worker_entry_points.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/horde_worker_regen/download_models.py b/horde_worker_regen/download_models.py index b4bdf1da..ae32af94 100644 --- a/horde_worker_regen/download_models.py +++ b/horde_worker_regen/download_models.py @@ -57,7 +57,7 @@ def download_all_models( del _ extra_comfyui_args = [] - if directml: + if directml is not None: extra_comfyui_args.append(f"--directml={directml}") hordelib.initialise(extra_comfyui_args=extra_comfyui_args) diff --git a/horde_worker_regen/process_management/worker_entry_points.py b/horde_worker_regen/process_management/worker_entry_points.py index f51e6e0e..80d0c4ab 100644 --- a/horde_worker_regen/process_management/worker_entry_points.py +++ b/horde_worker_regen/process_management/worker_entry_points.py @@ -65,7 +65,7 @@ def start_inference_process( if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") - if directml: + if directml is not None: extra_comfyui_args.append(f"--directml={directml}") models_not_to_force_load = ["flux"] @@ -158,7 +158,7 @@ def start_safety_process( if amd_gpu: extra_comfyui_args.append("--use-pytorch-cross-attention") - if directml: + if directml is not None: extra_comfyui_args.append(f"--directml={directml}") with logger.catch(reraise=True): From ed2798d512bbe0ef640d7b2d6e838ad63c9b4646 Mon Sep 17 00:00:00 2001 From: tazlin Date: Fri, 6 Dec 2024 08:14:27 -0500 Subject: [PATCH 19/22] style: fix --- .../process_management/worker_entry_points.py | 4 ++++ horde_worker_regen/run_worker.py | 15 +++++++++++++-- tests/test_sdk_models.py | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/horde_worker_regen/process_management/worker_entry_points.py b/horde_worker_regen/process_management/worker_entry_points.py index 80d0c4ab..751352f6 100644 --- a/horde_worker_regen/process_management/worker_entry_points.py +++ b/horde_worker_regen/process_management/worker_entry_points.py @@ -41,6 +41,8 @@ def start_inference_process( Defaults to False. amd_gpu (bool, optional): If true, the process will attempt to use AMD GPU-specific optimisations. Defaults to False. + directml (int | None, optional): If not None, the process will attempt to use DirectML \ + with the specified device """ with contextlib.nullcontext(): # contextlib.redirect_stdout(None), contextlib.redirect_stderr(None): logger.remove() @@ -137,6 +139,8 @@ def start_safety_process( high_memory_mode (bool, optional): If true, the process will attempt to use more memory. Defaults to False. amd_gpu (bool, optional): If true, the process will attempt to use AMD GPU-specific optimisations. Defaults to False. + directml (int | None, optional): If not None, the process will attempt to use DirectML \ + with the specified device """ with contextlib.nullcontext(): # contextlib.redirect_stdout(), contextlib.redirect_stderr(): logger.remove() diff --git a/horde_worker_regen/run_worker.py b/horde_worker_regen/run_worker.py index 51ca635d..4525a022 100644 --- a/horde_worker_regen/run_worker.py +++ b/horde_worker_regen/run_worker.py @@ -18,7 +18,13 @@ from loguru import logger -def main(ctx: BaseContext, load_from_env_vars: bool = False, *, amd_gpu: bool = False, directml: int | None = None,) -> None: +def main( + ctx: BaseContext, + load_from_env_vars: bool = False, + *, + amd_gpu: bool = False, + directml: int | None = None, +) -> None: """Check for a valid config and start the driver ('main') process for the reGen worker.""" from horde_model_reference.model_reference_manager import ModelReferenceManager from pydantic import ValidationError @@ -213,7 +219,12 @@ def init() -> None: # We only need to download the legacy DBs once, so we do it here instead of in the worker processes - main(multiprocessing.get_context("spawn"), args.load_config_from_env_vars, amd_gpu=args.amd, directml=args.directml,) + main( + multiprocessing.get_context("spawn"), + args.load_config_from_env_vars, + amd_gpu=args.amd, + directml=args.directml, + ) if __name__ == "__main__": diff --git a/tests/test_sdk_models.py b/tests/test_sdk_models.py index acb6dce9..8d71deec 100644 --- a/tests/test_sdk_models.py +++ b/tests/test_sdk_models.py @@ -7,7 +7,7 @@ def test_skipped_status_handles_unknown_fields() -> None: # printed without error. skipped_status = ImageGenerateJobPopSkippedStatus( max_pixels=100, - testing_field=1, + testing_field=1, # type: ignore ) assert skipped_status.max_pixels == 100 From 2277d3838bf3d680926161b2ceb7b4724e85fe8b Mon Sep 17 00:00:00 2001 From: tazlin Date: Fri, 6 Dec 2024 08:39:07 -0500 Subject: [PATCH 20/22] fix: explicit pin for torch-directml Torch versions, especially experimental plugins, are notorious for introducing breaking changes version to version. Pinning will help minimize this chance. --- requirements.directml.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.directml.txt b/requirements.directml.txt index f8442c9c..bd06bc1e 100644 --- a/requirements.directml.txt +++ b/requirements.directml.txt @@ -1,9 +1,9 @@ -torch-directml +torch-directml==0.2.5.dev240914 qrcode==7.4.2 # >8 breaks horde-engine 2.18.1 via the qr code generation nodes certifi # Required for SSL cert resolution -horde_sdk~=0.15.1 +horde_sdk~=0.16.4 horde_safety~=0.2.3 horde_engine~=2.18.1 horde_model_reference>=0.9.1 From 5c71e5b8902d45f47713021c909be21207bd9940 Mon Sep 17 00:00:00 2001 From: tazlin Date: Fri, 6 Dec 2024 08:46:33 -0500 Subject: [PATCH 21/22] tests: flexible reqs/deps checking for more backends With the introduction of directml and the current landscape, its likely we may yet increase the number of supported driving technologies, so I've refactored the relevant tests to be more modular --- tests/conftest.py | 38 ++++++++++-------------- tests/test_horde_dep_updates.py | 51 +++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 69a1fe65..ff81a1cf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -17,6 +17,7 @@ def init_hordelib() -> None: PRECOMMIT_FILE_PATH = Path(__file__).parent.parent / ".pre-commit-config.yaml" REQUIREMENTS_FILE_PATH = Path(__file__).parent.parent / "requirements.txt" ROCM_REQUIREMENTS_FILE_PATH = Path(__file__).parent.parent / "requirements.rocm.txt" +DIRECTML_REQUIREMENTS_FILE_PATH = Path(__file__).parent.parent / "requirements.directml.txt" TRACKED_DEPENDENCIES = [ "horde_sdk", @@ -34,10 +35,9 @@ def tracked_dependencies() -> list[str]: return TRACKED_DEPENDENCIES -@pytest.fixture(scope="session") -def horde_dependency_versions() -> dict[str, str]: - """Get the versions of horde dependencies from the requirements file.""" - with open(REQUIREMENTS_FILE_PATH) as f: +def get_dependency_versions(requirements_file_path: str) -> dict[str, str]: + """Get the versions of horde dependencies from the given requirements file.""" + with open(requirements_file_path) as f: requirements = f.readlines() dependencies = {} @@ -60,27 +60,19 @@ def horde_dependency_versions() -> dict[str, str]: return dependencies +@pytest.fixture(scope="session") +def horde_dependency_versions() -> dict[str, str]: + """Get the versions of horde dependencies from the requirements file.""" + return get_dependency_versions(REQUIREMENTS_FILE_PATH) + + @pytest.fixture(scope="session") def rocm_horde_dependency_versions() -> dict[str, str]: """Get the versions of horde dependencies from the ROCm requirements file.""" - with open(ROCM_REQUIREMENTS_FILE_PATH) as f: - requirements = f.readlines() + return get_dependency_versions(ROCM_REQUIREMENTS_FILE_PATH) - dependencies = {} - for req in requirements: - for dep in TRACKED_DEPENDENCIES: - if req.startswith(dep): - if "==" in req: - version = req.split("==")[1].strip() - elif "~=" in req: - version = req.split("~=")[1].strip() - elif ">=" in req: - version = req.split(">=")[1].strip() - else: - raise ValueError(f"Unsupported version pin: {req}") - # Strip any info starting from the `+` character - version = version.split("+")[0] - dependencies[dep] = version - - return dependencies +@pytest.fixture(scope="session") +def directml_horde_dependency_versions() -> dict[str, str]: + """Get the versions of horde dependencies from the DirectML requirements file.""" + return get_dependency_versions(DIRECTML_REQUIREMENTS_FILE_PATH) diff --git a/tests/test_horde_dep_updates.py b/tests/test_horde_dep_updates.py index 0122a470..3f3f9279 100644 --- a/tests/test_horde_dep_updates.py +++ b/tests/test_horde_dep_updates.py @@ -43,33 +43,54 @@ def test_horde_update_runtime_updating(horde_dependency_versions: dict[str, str] assert found_line, "No initial torch install command found" -def test_different_requirements_files_match( - horde_dependency_versions: dict[str, str], - rocm_horde_dependency_versions: list[tuple[str, str]], +def check_dependency_versions( + main_deps: dict[str, str], + other_deps: dict[str, str], + other_name: str, ) -> None: - """Check that the versions of horde deps. in the main and rocm requirements files match.""" - rocm_deps = dict(rocm_horde_dependency_versions) + """Check that the main requirements file is consistent with the other requirements file. - for dep in horde_dependency_versions: + Args: + main_deps (dict[str, str]): The versions of the dependencies in the main requirements file. + other_deps (dict[str, str]): The versions of the dependencies in the other requirements file. + other_name (str): The name of the other requirements file. + + Raises: + AssertionError: If the versions of the dependencies are inconsistent. + """ + for dep in main_deps: if dep == "torch": logger.warning( - f"Skipping torch version check (main: {horde_dependency_versions[dep]}, rocm: {rocm_deps[dep]})", + f"Skipping torch version check (main: {main_deps[dep]}, {other_name}: {other_deps[dep]})", ) continue - assert dep in rocm_deps, f"Dependency {dep} not found in rocm requirements file" + assert dep in other_deps, f"Dependency {dep} not found in {other_name} requirements file" assert ( - horde_dependency_versions[dep] == rocm_deps[dep] - ), f"Dependency {dep} has different versions in main and rocm requirements files" + main_deps[dep] == other_deps[dep] + ), f"Dependency {dep} has different versions in main and {other_name} requirements files" - for dep in rocm_deps: + for dep in other_deps: if dep == "torch": logger.warning( - f"Skipping torch version check (main: {horde_dependency_versions[dep]}, rocm: {rocm_deps[dep]})", + f"Skipping torch version check (main: {main_deps[dep]}, {other_name}: {other_deps[dep]})", ) continue - assert dep in horde_dependency_versions, f"Dependency {dep} not found in main requirements file" + assert dep in main_deps, f"Dependency {dep} not found in main requirements file" assert ( - rocm_deps[dep] == horde_dependency_versions[dep] - ), f"Dependency {dep} has different versions in main and rocm requirements files" + other_deps[dep] == main_deps[dep] + ), f"Dependency {dep} has different versions in main and {other_name} requirements files" + + +def test_different_requirements_files_match( + horde_dependency_versions: dict[str, str], + rocm_horde_dependency_versions: list[tuple[str, str]], + directml_horde_dependency_versions: list[tuple[str, str]], +) -> None: + """Check that the versions of horde deps. in the all of the various requirements files are consistent.""" + rocm_deps = dict(rocm_horde_dependency_versions) + directml_deps = dict(directml_horde_dependency_versions) + + check_dependency_versions(horde_dependency_versions, rocm_deps, "rocm") + check_dependency_versions(horde_dependency_versions, directml_deps, "directml") From 6206cff8ac84fb3085c67d9dfd378c7f16ef91f2 Mon Sep 17 00:00:00 2001 From: tazlin Date: Fri, 6 Dec 2024 09:13:29 -0500 Subject: [PATCH 22/22] style: fix --- tests/conftest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index ff81a1cf..9651bb0d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,8 +35,10 @@ def tracked_dependencies() -> list[str]: return TRACKED_DEPENDENCIES -def get_dependency_versions(requirements_file_path: str) -> dict[str, str]: +def get_dependency_versions(requirements_file_path: str | Path) -> dict[str, str]: """Get the versions of horde dependencies from the given requirements file.""" + requirements_file_path = Path(requirements_file_path) + with open(requirements_file_path) as f: requirements = f.readlines()