Tổng quan về CUDA theo cách ẩn

CUDA kín sử dụng một phiên bản CUDA có thể tải xuống cụ thể thay vì CUDA được cài đặt cục bộ của người dùng. Bazel sẽ tải các bản phân phối CUDA, CUDNN và NCCL xuống, sau đó sử dụng các thư viện và công cụ CUDA làm phần phụ thuộc trong nhiều mục tiêu Bazel. Điều này cho phép tạo nhiều bản dựng có thể tái tạo hơn cho các dự án Học máy của Google và các phiên bản CUDA được hỗ trợ.

Các phiên bản CUDA, CUDNN khép kín được hỗ trợ

Các phiên bản CUDA được hỗ trợ được chỉ định trong từ điển CUDA_REDIST_JSON_DICT, third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

Các phiên bản CUDNN được hỗ trợ được chỉ định trong từ điển CUDNN_REDIST_JSON_DICT, third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

Các tệp .bazelrc của từng dự án có các biến môi trường HERMETIC_CUDA_VERSION, HERMETIC_CUDNN_VERSION được đặt thành các phiên bản được sử dụng theo mặc định khi --config=cuda được chỉ định trong các tuỳ chọn lệnh Bazel.

Các biến môi trường kiểm soát các phiên bản CUDA/CUDNN kín

Biến môi trường HERMETIC_CUDA_VERSION phải bao gồm phiên bản CUDA chính, phụ và bản vá, ví dụ: 12.3.2. Biến môi trường HERMETIC_CUDNN_VERSION phải bao gồm phiên bản CUDNN chính, phụ và bản vá, ví dụ: 9.1.1.

Ba cách để đặt biến môi trường cho các lệnh 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"

Nếu không có HERMETIC_CUDA_VERSIONHERMETIC_CUDNN_VERSION, thì các quy tắc kho lưu trữ CUDA/CUDNN kín sẽ tra cứu các giá trị biến môi trường TF_CUDA_VERSIONTF_CUDNN_VERSION. Điều này được thực hiện để tương thích ngược với các quy tắc kho lưu trữ CUDA/CUDNN không kín.

Việc liên kết giữa phiên bản CUDA và phiên bản phân phối NCCL cần tải xuống được chỉ định trong third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl

Định cấu hình CUDA kín

  1. Trong dự án phụ thuộc vào XLA, hãy thêm các dòng sau vào cuối tệp 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. Để chọn các phiên bản cụ thể của CUDA và CUDNN kín, hãy đặt các biến môi trường HERMETIC_CUDA_VERSIONHERMETIC_CUDNN_VERSION tương ứng. Chỉ sử dụng các phiên bản được hỗ trợ. Bạn có thể đặt các biến môi trường trực tiếp trong shell hoặc trong tệp .bazelrc như minh hoạ dưới đây:

    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. Để bật CUDA kín trong quá trình thực thi kiểm thử hoặc khi chạy tệp nhị phân thông qua bazel, hãy nhớ thêm cờ --@local_config_cuda//cuda:include_cuda_libs=true vào lệnh bazel. Bạn có thể cung cấp trực tiếp trong một shell hoặc trong .bazelrc:

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

    Cần có cờ này để đảm bảo rằng các phần phụ thuộc CUDA được cung cấp đúng cách để kiểm thử các tệp thực thi. Theo mặc định, cờ này là false để tránh việc ghép nối không mong muốn giữa các bánh xe Python do Google phát hành với tệp nhị phân CUDA.

  4. Để thực thi chế độ tương thích chuyển tiếp CUDA, hãy thêm cờ --@cuda_driver//:enable_forward_compatibility=true vào lệnh bazel. Bạn có thể cung cấp trực tiếp trong một shell hoặc trong .bazelrc:

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

    Giá trị cờ mặc định là false.

    Khi chế độ tương thích chuyển tiếp CUDA bị tắt, các mục tiêu Bazel sẽ sử dụng Trình điều khiển chế độ người dùng và Trình điều khiển chế độ hạt nhân được cài đặt sẵn trên hệ thống.

    Khi chế độ tương thích chuyển tiếp CUDA được bật, các mục tiêu Bazel sẽ sử dụng Trình điều khiển chế độ người dùng từ quá trình phân phối lại trình điều khiển CUDA được tải xuống bộ nhớ đệm Bazel và Trình điều khiển chế độ hạt nhân được cài đặt sẵn trên hệ thống. Trình điều khiển này cho phép bật các tính năng mới của Bộ công cụ CUDA trong khi sử dụng Trình điều khiển chế độ hạt nhân cũ.

    Bạn chỉ nên thực thi chế độ tương thích chuyển tiếp khi thích hợp – xem tài liệu của NVIDIA để biết thông tin chi tiết.

Nâng cấp phiên bản CUDA/CUDNN kín

  1. Tạo và gửi yêu cầu kéo với các từ điển CUDA_REDIST_JSON_DICT, CUDA_REDIST_JSON_DICT đã cập nhật trong third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl.

    Cập nhật CUDA_NCCL_WHEELS trong third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl nếu cần.

    Cập nhật REDIST_VERSIONS_TO_BUILD_TEMPLATES trong third_party/gpus/cuda/hermetic/cuda_redist_versions.bzl nếu cần.

  2. Đối với mỗi dự án học máy của Google, hãy tạo một yêu cầu lấy dữ liệu riêng biệt với HERMETIC_CUDA_VERSIONHERMETIC_CUDNN_VERSION đã cập nhật trong tệp .bazelrc.

    Các lần thực thi công việc trước khi gửi PR sẽ chạy các kiểm thử bazel và tải các bản phân phối CUDA/CUDNN kín xuống. Xác minh rằng các công việc gửi trước đã vượt qua trước khi gửi yêu cầu thay đổi.

Trỏ đến các bản phân phối lại CUDA/CUDNN/NCCL trên hệ thống tệp cục bộ

Bạn có thể sử dụng các thư mục CUDA/CUDNN/NCCL cục bộ làm nguồn phân phối lại. Bạn cần có thêm các biến môi trường sau:

LOCAL_CUDA_PATH
LOCAL_CUDNN_PATH
LOCAL_NCCL_PATH

Ví dụ:

# 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"

Cấu trúc của các thư mục bên trong thư mục CUDA sẽ như sau (như thể các bản phân phối lại được lưu trữ đã được giải nén vào một nơi):

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

Cấu trúc của các thư mục bên trong thư mục CUDNN sẽ như sau:

<LOCAL_CUDNN_PATH>
    include/
    lib/

Cấu trúc của các thư mục bên trong thư mục NCCL sẽ như sau:

<LOCAL_NCCL_PATH>
    include/
    lib/

Các bản lưu trữ CUDA/CUDNN tuỳ chỉnh và bánh xe NCCL

Có 3 lựa chọn cho phép sử dụng bản phân phối CUDA/CUDNN tuỳ chỉnh.

Tệp JSON tuỳ chỉnh để phân phối lại CUDA/CUDNN

Tuỳ chọn này cho phép sử dụng các bản phân phối tuỳ chỉnh cho tất cả phần phụ thuộc CUDA/CUDNN trong các dự án Học máy của Google.

  1. Tạo tệp cuda_redist.json và/hoặc cudnn_redist.json.

    Chương trình cuda_redist.json theo định dạng dưới đây:

    {
       "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",
          }
       },
    }
    

    Chương trình cudnn_redist.json tuân theo định dạng bên dưới:

    {
       "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",
             }
          }
       }
    }
    

    Bạn có thể thay thế trường relative_path bằng full_path cho URL đầy đủ và đường dẫn cục bộ tuyệt đối bắt đầu bằng file:///.

  2. Trong dự án thứ cấp phụ thuộc vào XLA, hãy cập nhật lệnh gọi kho lưu trữ JSON cuda kín trong tệp WORKSPACE. Bạn được phép sử dụng cả đường liên kết web và đường dẫn tệp cục bộ. Ví dụ:

    _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,
    )
    

    Nếu tệp JSON chứa đường dẫn tương đối đến các bản phân phối, thì bạn phải cập nhật tiền tố đường dẫn trong lệnh gọi cuda_redist_init_repositories()cudnn_redist_init_repository(). Ví dụ:

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

Bản phân phối CUDA/CUDNN tuỳ chỉnh

Tuỳ chọn này cho phép sử dụng các bản phân phối tuỳ chỉnh cho một số phần phụ thuộc CUDA/CUDNN trong các dự án học máy của Google.

  1. Trong dự án hạ nguồn phụ thuộc vào XLA, hãy xoá các dòng bên dưới:

    <...>
       "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. Trong cùng một tệp WORKSPACE, hãy tạo từ điển có đường dẫn phân phối.

    Từ điển có các bản phân phối CUDA hiển thị theo định dạng bên dưới:

    _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",
          }
       },
    }
    

    Từ điển có các bản phân phối CUDNN hiển thị theo định dạng bên dưới:

    _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",
             }
          }
       }
    }
    

    Bạn có thể thay thế trường relative_path bằng full_path cho URL đầy đủ và đường dẫn cục bộ tuyệt đối bắt đầu bằng file:///.

  3. Trong cùng tệp WORKSPACE, hãy truyền các từ điển đã tạo vào quy tắc của kho lưu trữ. Nếu từ điển chứa đường dẫn tương đối đến các bản phân phối, thì bạn nên cập nhật tiền tố đường dẫn trong lệnh gọi 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/"
    )
    

    Kết hợp các lựa chọn ở trên

Trong ví dụ bên dưới, CUDA_REDIST_JSON_DICT được hợp nhất với dữ liệu JSON tuỳ chỉnh trong _CUDA_JSON_DICTCUDNN_REDIST_JSON_DICT được hợp nhất với _CUDNN_JSON_DICT.

Dữ liệu phân phối trong _CUDA_DIST_DICT ghi đè nội dung của tệp JSON CUDA thu được và dữ liệu phân phối trong _CUDNN_DIST_DICT ghi đè nội dung của tệp JSON CUDNN thu được. Dữ liệu về bánh xe NCCL được hợp nhất từ 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,
)

NÊN DỪNG SỬ DỤNG: Việc sử dụng CUDA/CUDNN không kín

Mặc dù chúng tôi đã ngừng sử dụng CUDA/CUDNN không khép kín, nhưng vẫn có thể dùng cho một số thử nghiệm hiện chưa được hỗ trợ chính thức (ví dụ: tạo bánh xe trên Windows bằng CUDA).

Dưới đây là các bước để sử dụng CUDA không kín được cài đặt cục bộ trong các dự án Google ML:

  1. Xoá các lệnh gọi đến các quy tắc kho lưu trữ CUDA kín từ tệp WORKSPACE của dự án phụ thuộc vào XLA.

  2. Thêm các lệnh gọi đến các quy tắc kho lưu trữ CUDA không kín vào cuối tệp WORKSPACE.

    Đối với XLA và 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")
    

    Đối với 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. Thiết lập các biến môi trường sau trực tiếp trong shell hoặc trong tệp .bazelrc như minh hoạ bên dưới:

    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>
    

    Xin lưu ý rằng TF_CUDA_VERSIONTF_CUDNN_VERSION chỉ nên bao gồm các phiên bản chính và nhỏ (ví dụ: 12.3 cho CUDA và 9.1 cho CUDNN).

  4. Bây giờ, bạn có thể chạy lệnh bazel để sử dụng CUDA và CUDNN đã cài đặt cục bộ.

    Đối với XLA, bạn không cần thay đổi các tuỳ chọn lệnh.

    Đối với JAX, hãy sử dụng cờ --override_repository=tsl=<tsl_path> trong các tuỳ chọn lệnh Bazel.

    Đối với Tensorflow, hãy sử dụng cờ --override_repository=local_tsl=<tsl_path> trong các tuỳ chọn lệnh Bazel.