Hermetyczne CUDA

Hermetyczna CUDA używa określonej wersji CUDA do pobrania zamiast lokalnej wersji CUDA użytkownika. 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. Dzięki temu projekty ML Google i obsługiwane wersje CUDA są bardziej odtwarzalne.

Obsługiwane wersje hermetyczne CUDA i CUDNN

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.

Pliki .bazelrc poszczególnych projektów mają zmienne środowiskowe HERMETIC_CUDA_VERSION (HERMETIC_CUDNN_VERSION) ustawione na wersje używane domyślnie, gdy w opcjach poleceń Bazel określono --config=cuda.

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

Zmienna środowiskowa HERMETIC_CUDA_VERSION powinna składać się z głównej, podrzędnej i poprawkowej wersji 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 nie ma HERMETIC_CUDA_VERSION i HERMETIC_CUDNN_VERSION, hermetyczne reguły repozytorium CUDA/CUDNN szukają wartości zmiennych środowiskowych TF_CUDA_VERSION i TF_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(
       "@tsl//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(
       "@tsl//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(
       "@tsl//third_party/gpus/cuda/hermetic:cuda_configure.bzl",
       "cuda_configure",
    )
    
    cuda_configure(name = "local_config_cuda")
    
    load(
       "@tsl//third_party/nccl/hermetic:nccl_redist_init_repository.bzl",
       "nccl_redist_init_repository",
    )
    
    nccl_redist_init_repository()
    
    load(
       "@tsl//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 w 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 pliku 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
    

    Ta flaga jest potrzebna do sprawdzenia, czy zależności CUDA są prawidłowo podane na potrzeby 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 egzekwować tryb zgodności CUDA, dodaj do polecenia bazel flagę --@cuda_driver//:enable_forward_compatibility=true. 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 CUDA jest wyłączony, cele Bazel będą używać trybów użytkownika i sterowników trybu jądra zainstalowanych w systemie.

    Gdy włączony jest tryb zgodności CUDA, cele Bazel używają sterownika trybu użytkownika z redystrybucji sterowników CUDA pobranego do pamięci podręcznej Bazel i sterownika trybu jądra 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ć wymuszony 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.

  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 redystrybucji 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 być następująca (tak jakby zarchiwizowane redystrybucje 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 wyglądać tak:

<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 redystrybucji 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 lokalnych plików. 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, prefiks ścieżki należy zaktualizować w wywołaniach cuda_redist_init_repositories() i 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 poniższy 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 następujący 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 dystrybucyjne w _CUDA_DIST_DICT zastępują zawartość wynikowego pliku JSON CUDA, a dane dystrybucyjne w _CUDNN_DIST_DICT zastępują zawartość wynikowego pliku JSON CUDNN. Dane kół NCCL zostały scalone z danych CUDA_NCCL_WHEELS i _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,
)

PRZESZŁY: nieszczelny sposób korzystania z 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 końcu pliku WORKSPACE.

    XLA i JAX:

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

    W przypadku TensorFlow:

    load("@local_tsl//third_party/gpus:cuda_configure.bzl", "cuda_configure")
    cuda_configure(name = "local_config_cuda")
    load("@local_tsl//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.