Hermetyczne CUDA

Hermetic CUDA używa określonej wersji CUDA do pobrania zamiast zainstalowanej lokalnie wersji CUDA. Bazel pobierze dystrybucje CUDA, CUDNN i NCCL, a następnie użyje bibliotek i narzędzi CUDA jako zależności w różnych celach Bazel. Umożliwia to tworzenie bardziej powtarzalnych wersji w przypadku projektów uczenia maszynowego Google i obsługiwanych wersji CUDA.

Obsługiwane wersje CUDA i CUDNN w trybie hermetycznym

Obsługiwane wersje CUDA są określone w słowniku CUDA_REDIST_JSON_DICT third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

Obsługiwane wersje CUDNN są określone w pliku CUDNN_REDIST_JSON_DICT dictionary, third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

W plikach .bazelrc poszczególnych projektów zmienne środowiskowe HERMETIC_CUDA_VERSIONHERMETIC_CUDNN_VERSION są ustawione na wersje używane domyślnie, gdy w opcjach polecenia Bazel podano wartość --config=cuda.

zmienne środowiskowe kontrolujące hermetyczne wersje CUDA/CUDNN;

Zmienna środowiskowa HERMETIC_CUDA_VERSION powinna składać się z wersji głównej, podrzędnej i wersji poprawki CUDA, np. 12.3.2. Zmienna środowiskowa HERMETIC_CUDNN_VERSION powinna zawierać wersję główną, podrzędną i wersję poprawki CUDNN, np. 9.1.1.

Trzy sposoby ustawiania zmiennych środowiskowych dla poleceń Bazel:

# Add an entry to your `.bazelrc` file
build:cuda --repo_env=HERMETIC_CUDA_VERSION="12.3.2"
build:cuda --repo_env=HERMETIC_CUDNN_VERSION="9.1.1"

# OR pass it directly to your specific build command
bazel build --config=cuda <target> \
--repo_env=HERMETIC_CUDA_VERSION="12.3.2" \
--repo_env=HERMETIC_CUDNN_VERSION="9.1.1"

# If .bazelrc doesn't have corresponding entries and the environment variables
# are not passed to bazel command, you can set them globally in your shell:
export HERMETIC_CUDA_VERSION="12.3.2"
export HERMETIC_CUDNN_VERSION="9.1.1"

Jeśli zmienne HERMETIC_CUDA_VERSIONHERMETIC_CUDNN_VERSION nie są dostępne, reguły hermetycznego repozytorium CUDA/CUDNN będą wyszukiwać wartości zmiennych środowiskowych TF_CUDA_VERSIONTF_CUDNN_VERSION. Jest to konieczne ze względu na zgodność wsteczną z niehermetycznymi regułami repozytorium CUDA/CUDNN.

Mapowanie wersji CUDA i wersji dystrybucji NCCL do pobrania jest określone w pliku third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

Konfigurowanie hermetycznego CUDA

  1. W pochodzącym projekcie zależnym od XLA dodaj te wiersze do dołu pliku WORKSPACE:

    load(
       "@xla//third_party/gpus/cuda/hermetic:cuda_json_init_repository.bzl",
       "cuda_json_init_repository",
    )
    
    cuda_json_init_repository()
    
    load(
       "@cuda_redist_json//:distributions.bzl",
       "CUDA_REDISTRIBUTIONS",
       "CUDNN_REDISTRIBUTIONS",
    )
    load(
       "@xla//third_party/gpus/cuda/hermetic:cuda_redist_init_repositories.bzl",
       "cuda_redist_init_repositories",
       "cudnn_redist_init_repository",
    )
    
    cuda_redist_init_repositories(
       cuda_redistributions = CUDA_REDISTRIBUTIONS,
    )
    
    cudnn_redist_init_repository(
       cudnn_redistributions = CUDNN_REDISTRIBUTIONS,
    )
    
    load(
       "@xla//third_party/gpus/cuda/hermetic:cuda_configure.bzl",
       "cuda_configure",
    )
    
    cuda_configure(name = "local_config_cuda")
    
    load(
       "@xla//third_party/nccl/hermetic:nccl_redist_init_repository.bzl",
       "nccl_redist_init_repository",
    )
    
    nccl_redist_init_repository()
    
    load(
       "@xla//third_party/nccl/hermetic:nccl_configure.bzl",
       "nccl_configure",
    )
    
    nccl_configure(name = "local_config_nccl")
    
  2. Aby wybrać konkretne wersje hermetyczne CUDA i CUDNN, odpowiednio ustaw zmienne środowiskowe HERMETIC_CUDA_VERSIONHERMETIC_CUDNN_VERSION. Używaj tylko obsługiwanych wersji. Zmienne środowiskowe możesz ustawić bezpośrednio w powłoce lub pliku .bazelrc, jak pokazano poniżej:

    build:cuda --repo_env=HERMETIC_CUDA_VERSION="12.3.2"
    build:cuda --repo_env=HERMETIC_CUDNN_VERSION="9.1.1"
    build:cuda --repo_env=HERMETIC_CUDA_COMPUTE_CAPABILITIES="sm_50,sm_60,sm_70,sm_80,compute_90"
    
  3. Aby włączyć hermetyczną architekturę CUDA podczas wykonywania testu lub uruchamiania binarnego za pomocą bazel, dodaj do polecenia bazel flagę --@local_config_cuda//cuda:include_cuda_libs=true. Możesz podać je bezpośrednio w oprogramowaniu lub w pliku .bazelrc:

    build:cuda --@local_config_cuda//cuda:include_cuda_libs=true
    

    Ten parametr jest potrzebny, aby zapewnić prawidłowe dostarczenie zależności CUDA do testowania plików wykonywalnych. Domyślnie flaga ma wartość fałsz, aby uniknąć niechcianego powiązania pakietów Pythona opublikowanych przez Google z binarnymi bibliotekami CUDA.

  4. Aby wymusić tryb zgodności wstecznej CUDA, dodaj flagę --@cuda_driver//:enable_forward_compatibility=true do polecenia bazel. Możesz podać je bezpośrednio w oprogramowaniu lub w pliku .bazelrc:

    test:cuda --@cuda_driver//:enable_forward_compatibility=true
    

    Wartością domyślną flagi jest false.

    Gdy tryb zgodności wstecznej CUDA jest wyłączony, cele Bazel będą używać wbudowanych w system sterowników w trybie użytkownika i trybie jądra.

    Gdy tryb zgodności wstecznej CUDA jest włączony, cele Bazel będą używać sterownika w trybie użytkownika z ponownego rozpowszechniania sterownika CUDA pobranego do pamięci podręcznej Bazel oraz sterownika w trybie jądra wstępnie zainstalowanego w systemie. Umożliwia włączenie nowych funkcji CUDA Toolkit przy użyciu starszego sterownika w trybie jądra.

    Tryb zgodności wstecznej powinien być stosowany tylko wtedy, gdy jest to właściwe. Szczegółowe informacje znajdziesz w dokumentacji Nvidii.

Uaktualnij hermetyczną wersję CUDA/CUDNN

  1. Utwórz i prześlij prośbę o przechwycenie z aktualnymi słownikami CUDA_REDIST_JSON_DICTCUDA_REDIST_JSON_DICT w pliku third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

    W razie potrzeby zaktualizuj CUDA_NCCL_WHEELS w pliku third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

    W razie potrzeby zaktualizuj REDIST_VERSIONS_TO_BUILD_TEMPLATES w pliku third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

    W razie potrzeby zaktualizuj PTX_VERSION_DICT w pliku third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

  2. W przypadku każdego projektu Google ML utwórz oddzielne żądanie pull z aktualnymi wartościami HERMETIC_CUDA_VERSIONHERMETIC_CUDNN_VERSION w pliku .bazelrc.

    Wykonywanie zadań przed przesłaniem PR uruchamia testy bazel i pobiera hermetyczne dystrybucje CUDA/CUDNN. Przed przesłaniem PR sprawdź, czy zadania przed przesłaniem zostały ukończone.

Wskazywanie dystrybucji CUDA/CUDNN/NCCL w lokalnym systemie plików

Jako źródła rozpowszechniania możesz użyć lokalnych katalogów CUDA/CUDNN/NCCL. Wymagane są te dodatkowe zmienne środowiskowe:

LOCAL_CUDA_PATH
LOCAL_CUDNN_PATH
LOCAL_NCCL_PATH

Przykład:

# Add an entry to your `.bazelrc` file
build:cuda --repo_env=LOCAL_CUDA_PATH="/foo/bar/nvidia/cuda"
build:cuda --repo_env=LOCAL_CUDNN_PATH="/foo/bar/nvidia/cudnn"
build:cuda --repo_env=LOCAL_NCCL_PATH="/foo/bar/nvidia/nccl"

# OR pass it directly to your specific build command
bazel build --config=cuda <target> \
--repo_env=LOCAL_CUDA_PATH="/foo/bar/nvidia/cuda" \
--repo_env=LOCAL_CUDNN_PATH="/foo/bar/nvidia/cudnn" \
--repo_env=LOCAL_NCCL_PATH="/foo/bar/nvidia/nccl"

# If .bazelrc doesn't have corresponding entries and the environment variables
# are not passed to bazel command, you can set them globally in your shell:
export LOCAL_CUDA_PATH="/foo/bar/nvidia/cuda"
export LOCAL_CUDNN_PATH="/foo/bar/nvidia/cudnn"
export LOCAL_NCCL_PATH="/foo/bar/nvidia/nccl"

Struktura folderów w katalogu CUDA powinna wyglądać tak (jakby zarchiwizowane pliki do ponownego rozpowszechniania zostały rozpakowane w jednym miejscu):

<LOCAL_CUDA_PATH>/
    include/
    bin/
    lib/
    nvvm/

Struktura folderów w katalogu CUDNN powinna być następująca:

<LOCAL_CUDNN_PATH>
    include/
    lib/

Struktura folderów w katalogu NCCL powinna być następująca:

<LOCAL_NCCL_PATH>
    include/
    lib/

Niestandardowe archiwa CUDA/CUDNN i koła NCCL

Dostępne są 3 opcje umożliwiające korzystanie z niestandardowych dystrybucji CUDA/CUDNN.

niestandardowe pliki JSON z rozpowszechnieniem CUDA/CUDNN.

Ta opcja umożliwia korzystanie z niestandardowych dystrybucji wszystkich zależności CUDA/CUDNN w projektach Google ML.

  1. Utwórz pliki cuda_redist.json lub cudnn_redist.json.

    cuda_redist.json wyświetlenia w formacie:

    {
       "cuda_cccl": {
          "linux-x86_64": {
             "relative_path": "cuda_cccl-linux-x86_64-12.4.99-archive.tar.xz",
          },
          "linux-sbsa": {
             "relative_path": "cuda_cccl-linux-sbsa-12.4.99-archive.tar.xz",
          }
       },
    }
    

    cudnn_redist.json wyświetlenia w formacie:

    {
       "cudnn": {
          "linux-x86_64": {
             "cuda12": {
             "relative_path": "cudnn/linux-x86_64/cudnn-linux-x86_64-9.0.0.312_cuda12-archive.tar.xz",
             }
          },
          "linux-sbsa": {
             "cuda12": {
             "relative_path": "cudnn/linux-sbsa/cudnn-linux-sbsa-9.0.0.312_cuda12-archive.tar.xz",
             }
          }
       }
    }
    

    W przypadku pełnych adresów URL i bezwzględnych ścieżek lokalnych rozpoczynających się od file:/// pole relative_path można zastąpić polem full_path.

  2. W pochodzącym projekcie zależnym od XLA zaktualizuj wywołanie hermetycznego repozytorium JSON cuda w pliku WORKSPACE. Dozwolone są zarówno linki internetowe, jak i ścieżki do plików lokalnych. Przykład:

    _CUDA_JSON_DICT = {
       "12.4.0": [
          "file:///home/user/Downloads/redistrib_12.4.0_updated.json",
       ],
    }
    
    _CUDNN_JSON_DICT = {
       "9.0.0": [
          "https://developer.download.nvidia.com/compute/cudnn/redist/redistrib_9.0.0.json",
       ],
    }
    
    cuda_json_init_repository(
       cuda_json_dict = _CUDA_JSON_DICT,
       cudnn_json_dict = _CUDNN_JSON_DICT,
    )
    

    Jeśli pliki JSON zawierają ścieżki względne do dystrybucji, należy zaktualizować prefiks ścieżki w wywołaniach cuda_redist_init_repositories()cudnn_redist_init_repository(). Przykład

    cuda_redist_init_repositories(
       cuda_redistributions = CUDA_REDISTRIBUTIONS,
       cuda_redist_path_prefix = "file:///usr/Downloads/dists/",
    )
    

Niestandardowe dystrybucje CUDA/CUDNN

Ta opcja umożliwia korzystanie z niestandardowych dystrybucji niektórych zależności CUDA/CUDNN w projektach Google ML.

  1. W pochodzącym projekcie zależnym od XLA usuń te wiersze:

    <...>
       "CUDA_REDIST_JSON_DICT",
    <...>
       "CUDNN_REDIST_JSON_DICT",
    <...>
    
    cuda_json_init_repository(
       cuda_json_dict = CUDA_REDIST_JSON_DICT,
       cudnn_json_dict = CUDNN_REDIST_JSON_DICT,
    )
    
    load(
       "@cuda_redist_json//:distributions.bzl",
       "CUDA_REDISTRIBUTIONS",
       "CUDNN_REDISTRIBUTIONS",
    )
    
  2. W tym samym pliku WORKSPACE utwórz słowniki z ścieżkami dystrybucji.

    Słownik z rozkładami CUDA ma następujący format:

    _CUSTOM_CUDA_REDISTRIBUTIONS = {
       "cuda_cccl": {
          "linux-x86_64": {
             "relative_path": "cuda_cccl-linux-x86_64-12.4.99-archive.tar.xz",
          },
          "linux-sbsa": {
             "relative_path": "cuda_cccl-linux-sbsa-12.4.99-archive.tar.xz",
          }
       },
    }
    

    Słownik z rozkładami CUDNN ma format:

    _CUSTOM_CUDNN_REDISTRIBUTIONS = {
       "cudnn": {
          "linux-x86_64": {
             "cuda12": {
             "relative_path": "cudnn/linux-x86_64/cudnn-linux-x86_64-9.0.0.312_cuda12-archive.tar.xz",
             }
          },
          "linux-sbsa": {
             "cuda12": {
             "relative_path": "cudnn/linux-sbsa/cudnn-linux-sbsa-9.0.0.312_cuda12-archive.tar.xz",
             }
          }
       }
    }
    

    W przypadku pełnych adresów URL i bezwzględnych ścieżek lokalnych rozpoczynających się od file:/// pole relative_path można zastąpić polem full_path.

  3. W tym samym pliku WORKSPACE przekaż utworzone słowniki do reguły repozytorium. Jeśli słowniki zawierają ścieżki względne do dystrybucji, należy zaktualizować prefiks ścieżki w wywołaniach cuda_redist_init_repositories()cudnn_redist_init_repository().

    cuda_redist_init_repositories(
       cuda_redistributions = _CUSTOM_CUDA_REDISTRIBUTIONS,
       cuda_redist_path_prefix = "file:///home/usr/Downloads/dists/",
    )
    
    cudnn_redist_init_repository(
       cudnn_redistributions = _CUSTOM_CUDNN_REDISTRIBUTIONS,
       cudnn_redist_path_prefix = "file:///home/usr/Downloads/dists/cudnn/"
    )
    

    Kombinacja powyższych opcji

W przykładzie poniżej element CUDA_REDIST_JSON_DICT jest scalany z elementem _CUDA_JSON_DICT zawierającym niestandardowe dane w formacie JSON, a element CUDNN_REDIST_JSON_DICT jest scalany z elementem _CUDNN_JSON_DICT.

Dane dystrybucji w pliku _CUDA_DIST_DICT zastępują zawartość utworzonego pliku JSON CUDA, a dane dystrybucji w pliku _CUDNN_DIST_DICT zastępują zawartość utworzonego pliku JSON CUDNN. Dane dotyczące kół NCCL są scalane z poziomu CUDA_NCCL_WHEELS_NCCL_WHEEL_DICT.

load(
    //third_party/gpus/cuda/hermetic:cuda_redist_versions.bzl",
    "CUDA_REDIST_PATH_PREFIX",
    "CUDA_NCCL_WHEELS",
    "CUDA_REDIST_JSON_DICT",
    "CUDNN_REDIST_PATH_PREFIX",
    "CUDNN_REDIST_JSON_DICT",
)

_CUDA_JSON_DICT = {
   "12.4.0": [
      "file:///usr/Downloads/redistrib_12.4.0_updated.json",
   ],
}

_CUDNN_JSON_DICT = {
   "9.0.0": [
      "https://developer.download.nvidia.com/compute/cudnn/redist/redistrib_9.0.0.json",
   ],
}

cuda_json_init_repository(
   cuda_json_dict = CUDA_REDIST_JSON_DICT | _CUDA_JSON_DICT,
   cudnn_json_dict = CUDNN_REDIST_JSON_DICT | _CUDNN_JSON_DICT,
)

load(
   "@cuda_redist_json//:distributions.bzl",
   "CUDA_REDISTRIBUTIONS",
   "CUDNN_REDISTRIBUTIONS",
)

load(
   "//third_party/gpus/cuda/hermetic:cuda_redist_init_repositories.bzl",
   "cuda_redist_init_repositories",
   "cudnn_redist_init_repository",
)

_CUDA_DIST_DICT = {
   "cuda_cccl": {
      "linux-x86_64": {
            "relative_path": "cuda_cccl-linux-x86_64-12.4.99-archive.tar.xz",
      },
      "linux-sbsa": {
            "relative_path": "cuda_cccl-linux-sbsa-12.4.99-archive.tar.xz",
      },
   },
   "libcusolver": {
      "linux-x86_64": {
            "full_path": "file:///usr/Downloads/dists/libcusolver-linux-x86_64-11.6.0.99-archive.tar.xz",
      },
      "linux-sbsa": {
         "relative_path": "libcusolver-linux-sbsa-11.6.0.99-archive.tar.xz",
      },
   },
}

_CUDNN_DIST_DICT = {
   "cudnn": {
      "linux-x86_64": {
            "cuda12": {
               "relative_path": "cudnn-linux-x86_64-9.0.0.312_cuda12-archive.tar.xz",
            },
      },
      "linux-sbsa": {
            "cuda12": {
               "relative_path": "cudnn-linux-sbsa-9.0.0.312_cuda12-archive.tar.xz",
            },
      },
   },
}

cudnn_redist_init_repositories(
   cuda_redistributions = CUDA_REDISTRIBUTIONS | _CUDA_DIST_DICT,
   cuda_redist_path_prefix = "file:///usr/Downloads/dists/",
)

cudnn_redist_init_repository(
   cudnn_redistributions = CUDNN_REDISTRIBUTIONS | _CUDNN_DIST_DICT,
   cudnn_redist_path_prefix = "file:///usr/Downloads/dists/cudnn/"
)

load(
    "//third_party/nccl/hermetic:nccl_redist_init_repository.bzl",
    "nccl_redist_init_repository",
)

_NCCL_WHEEL_DICT = {
   "12.4.0": {
      "x86_64-unknown-linux-gnu": {
            "url": "https://files.pythonhosted.org/packages/38/00/d0d4e48aef772ad5aebcf70b73028f88db6e5640b36c38e90445b7a57c45/nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl",
      },
   },
}

nccl_redist_init_repository(
   cuda_nccl_wheels = CUDA_NCCL_WHEELS | _NCCL_WHEEL_DICT,
)

PRZESZCZAJĄCY: nieszczelny dostęp do CUDA/CUDNN

Chociaż niehermetyczne korzystanie z CUDA/CUDNN jest wycofane, może być używane w przypadku niektórych eksperymentów, które nie są obecnie oficjalnie obsługiwane (np. tworzenie pakietów w Windows za pomocą CUDA).

Aby używać niehermetycznej karty CUDA zainstalowanej lokalnie w projektach Google ML:

  1. Usuń wywołania do hermetycznych reguł repozytorium CUDA z pliku WORKSPACE projektu zależnego od XLA.

  2. Dodaj wywołania niehermetycznych reguł repozytorium CUDA na dole pliku WORKSPACE.

    W przypadku XLA i JAX:

    load("@xla//third_party/gpus:cuda_configure.bzl", "cuda_configure")
    cuda_configure(name = "local_config_cuda")
    load("@xla//third_party/nccl:nccl_configure.bzl", "nccl_configure")
    nccl_configure(name = "local_config_nccl")
    

    W przypadku TensorFlow:

    load("@local_xla//third_party/gpus:cuda_configure.bzl", "cuda_configure")
    cuda_configure(name = "local_config_cuda")
    load("@local_xla//third_party/nccl:nccl_configure.bzl", "nccl_configure")
    nccl_configure(name = "local_config_nccl")
    
  3. Ustaw te zmienne środowiskowe bezpośrednio w powłoce lub pliku .bazelrc, jak pokazano poniżej:

    build:cuda --action_env=TF_CUDA_VERSION=<locally installed cuda version>
    build:cuda --action_env=TF_CUDNN_VERSION=<locally installed cudnn version>
    build:cuda --action_env=TF_CUDA_COMPUTE_CAPABILITIES=<CUDA compute capabilities>
    build:cuda --action_env=LD_LIBRARY_PATH=<CUDA/CUDNN libraries folder locations divided by : sign>
    build:cuda --action_env=CUDA_TOOLKIT_PATH=<preinstalled CUDA folder location>
    build:cuda --action_env=TF_CUDA_PATHS=<preinstalled CUDA/CUDNN folder locations divided by , sign>
    build:cuda --action_env=NCCL_INSTALL_PATH=<preinstalled NCCL library folder location>
    

    Pamiętaj, że TF_CUDA_VERSIONTF_CUDNN_VERSION powinny zawierać tylko wersje główne i pomniejsze (np. 12.3 dla CUDA i 9.1 dla CUDNN).

  4. Teraz możesz uruchomić polecenie bazel, aby korzystać z instalacji CUDA i CUDNN na komputerze lokalnym.

    W przypadku XLA nie trzeba wprowadzać żadnych zmian w opcjach polecenia.

    W przypadku JAX użyj flagi --override_repository=tsl=<tsl_path> w opcjach polecenia Bazel.

    W przypadku Tensorflow użyj flagi --override_repository=local_tsl=<tsl_path> w opcjach polecenia Bazel.