diff --git a/.github/workflows/ubuntu-wheel-sbsa.yml b/.github/workflows/ubuntu-wheel-sbsa.yml new file mode 100644 index 00000000000..54a3cf5e89f --- /dev/null +++ b/.github/workflows/ubuntu-wheel-sbsa.yml @@ -0,0 +1,194 @@ +name: Ubuntu Wheel SBSA CUDA +permissions: {} + +on: + workflow_dispatch: + inputs: + developer_build: + description: 'Set to OFF for Release wheels' + required: false + default: 'ON' + push: + branches: + - main + pull_request: + types: [opened, reopened, synchronize] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + GCE_CLI_GHA_VERSION: '416.0.0' # Fixed to avoid dependency on API changes + BUILD_CUDA_MODULE: 'ON' + +jobs: + build-wheel: + permissions: + contents: write # Release upload + name: Build SBSA CUDA wheel + runs-on: ubuntu-24.04-arm + strategy: + fail-fast: false + matrix: + python_version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + is_main: + - ${{ github.ref == 'refs/heads/main' }} + exclude: + - is_main: false + python_version: '3.10' + - is_main: false + python_version: '3.11' + - is_main: false + python_version: '3.12' + - is_main: false + python_version: '3.13' + env: + DEVELOPER_BUILD: ${{ github.event.inputs.developer_build || 'ON' }} + PYTHON_VERSION: ${{ matrix.python_version }} + CCACHE_TAR_NAME: open3d-ubuntu-2204-cuda-sbsa-ci-ccache + OPEN3D_CPU_RENDERING: true + BUILD_PYTORCH_OPS: 'ON' + # TensorFlow v2.20 only supports python 3.9-3.13 + BUILD_TENSORFLOW_OPS: ${{ matrix.python_version >= '3.14' && 'OFF' || 'ON' }} + steps: + - name: Checkout source code + uses: actions/checkout@v6 + - name: Maximize build space + run: | + source util/ci_utils.sh + maximize_ubuntu_github_actions_build_space + # Be verbose and explicit here such that a developer can directly copy the + # `docker/docker_build.sh xxx` command to execute locally. + - name: Docker build + run: | + if [ "${{ env.PYTHON_VERSION }}" = "3.10" ] && [ "${{ env.DEVELOPER_BUILD }}" = "ON" ]; then + docker/docker_build.sh cuda_wheel_py310_dev + elif [ "${{ env.PYTHON_VERSION }}" = "3.11" ] && [ "${{ env.DEVELOPER_BUILD }}" = "ON" ]; then + docker/docker_build.sh cuda_wheel_py311_dev + elif [ "${{ env.PYTHON_VERSION }}" = "3.12" ] && [ "${{ env.DEVELOPER_BUILD }}" = "ON" ]; then + docker/docker_build.sh cuda_wheel_py312_dev + elif [ "${{ env.PYTHON_VERSION }}" = "3.13" ] && [ "${{ env.DEVELOPER_BUILD }}" = "ON" ]; then + docker/docker_build.sh cuda_wheel_py313_dev + elif [ "${{ env.PYTHON_VERSION }}" = "3.14" ] && [ "${{ env.DEVELOPER_BUILD }}" = "ON" ]; then + docker/docker_build.sh cuda_wheel_py314_dev + elif [ "${{ env.PYTHON_VERSION }}" = "3.10" ] && [ "${{ env.DEVELOPER_BUILD }}" = "OFF" ]; then + docker/docker_build.sh cuda_wheel_py310 + elif [ "${{ env.PYTHON_VERSION }}" = "3.11" ] && [ "${{ env.DEVELOPER_BUILD }}" = "OFF" ]; then + docker/docker_build.sh cuda_wheel_py311 + elif [ "${{ env.PYTHON_VERSION }}" = "3.12" ] && [ "${{ env.DEVELOPER_BUILD }}" = "OFF" ]; then + docker/docker_build.sh cuda_wheel_py312 + elif [ "${{ env.PYTHON_VERSION }}" = "3.13" ] && [ "${{ env.DEVELOPER_BUILD }}" = "OFF" ]; then + docker/docker_build.sh cuda_wheel_py313 + elif [ "${{ env.PYTHON_VERSION }}" = "3.14" ] && [ "${{ env.DEVELOPER_BUILD }}" = "OFF" ]; then + docker/docker_build.sh cuda_wheel_py314 + fi + shopt -s failglob + PIP_PKG_NAME="$(basename ${GITHUB_WORKSPACE}/open3d-[0-9]*.whl)" + PIP_CPU_PKG_NAME="$(basename ${GITHUB_WORKSPACE}/open3d_cpu*.whl)" + echo "PIP_PKG_NAME=$PIP_PKG_NAME" >> $GITHUB_ENV + echo "PIP_CPU_PKG_NAME=$PIP_CPU_PKG_NAME" >> $GITHUB_ENV + - name: Upload wheel to GitHub artifacts + uses: actions/upload-artifact@v7 + with: + name: ${{ env.PIP_PKG_NAME }} + path: | + ${{ env.PIP_PKG_NAME }} + ${{ env.PIP_CPU_PKG_NAME }} + if-no-files-found: error + - name: Update devel release + if: ${{ github.ref == 'refs/heads/main' }} + env: + GH_TOKEN: ${{ github.token }} + run: | + .github/workflows/update_release.sh ${GITHUB_WORKSPACE}/${{ env.PIP_PKG_NAME }} \ + ${GITHUB_WORKSPACE}/${{ env.PIP_CPU_PKG_NAME }} + - name: GCloud CLI auth + if: ${{ github.ref == 'refs/heads/main' }} + uses: 'google-github-actions/auth@v3' + with: + project_id: ${{ secrets.GCE_PROJECT }} + credentials_json: '${{ secrets.GCE_SA_KEY_GPU_CI }}' + - name: GCloud CLI setup + if: ${{ github.ref == 'refs/heads/main' }} + uses: google-github-actions/setup-gcloud@v3 + with: + version: ${{ env.GCE_CLI_GHA_VERSION }} + project_id: ${{ secrets.GCE_PROJECT }} + - name: Upload ccache to GCS + if: ${{ github.ref == 'refs/heads/main' }} + run: | + gsutil cp ${GITHUB_WORKSPACE}/${{ env.CCACHE_TAR_NAME }}.tar.xz gs://open3d-ci-cache/ + + test-wheel-cpu: + name: Test SBSA CUDA wheel CPU + permissions: + contents: read + runs-on: ubuntu-24.04-arm + needs: [build-wheel] + strategy: + fail-fast: false + matrix: + python_version: ['3.10', '3.11', '3.12', '3.13', '3.14'] + is_main: + - ${{ github.ref == 'refs/heads/main' }} + exclude: + - is_main: false + python_version: '3.10' + - is_main: false + python_version: '3.11' + - is_main: false + python_version: '3.12' + - is_main: false + python_version: '3.13' + env: + OPEN3D_ML_ROOT: ${{ github.workspace }}/Open3D-ML + BUILD_PYTORCH_OPS: 'ON' + # TensorFlow v2.20 only supports python 3.9-3.13 + BUILD_TENSORFLOW_OPS: ${{ matrix.python_version >= '3.14' && 'OFF' || 'ON' }} + steps: + - name: Checkout source code + uses: actions/checkout@v6 + - name: Maximize build space + run: | + source util/ci_utils.sh + maximize_ubuntu_github_actions_build_space + - name: Checkout Open3D-ML source code + uses: actions/checkout@v6 + with: + repository: isl-org/Open3D-ML + ref: main + path: ${{ env.OPEN3D_ML_ROOT }} + - name: Download wheels + uses: actions/download-artifact@v8 + with: + pattern: open3d*-manylinux*.whl + merge-multiple: true + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python_version }} + - name: Test Python package + run: | + python -V + source util/ci_utils.sh + pi_tag=$(python -c "import sys; print(f'cp{sys.version_info.major}{sys.version_info.minor}')") + test_wheel open3d-[0-9]*-"$pi_tag"-*.whl + - name: Run Python unit tests + run: | + source util/ci_utils.sh + echo "Running Open3D python tests..." + run_python_tests + - name: Test Python package (CPU) + env: + BUILD_CUDA_MODULE: OFF + run: | + python -V + source util/ci_utils.sh + pi_tag=$(python -c "import sys; print(f'cp{sys.version_info.major}{sys.version_info.minor}')") + test_wheel open3d_cpu*-"$pi_tag"-*.whl + - name: Run Python unit tests (CPU) + run: | + source util/ci_utils.sh + echo "Running Open3D python tests (CPU wheel)..." + run_python_tests diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a375bea818b..c1e9eb85971 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -27,7 +27,7 @@ concurrency: cancel-in-progress: true env: - PIP_VER: "24.3.1" + PIP_VER: "26.0.1" CUDA_VERSION: "12.6.0" SRC_DIR: "D:\\a\\open3d\\open3d" BUILD_DIR: "C:\\Open3D\\build" @@ -76,7 +76,7 @@ jobs: # Installer arguments $CUDA_INSTALL_ARGS = "-s" # Required packages - $CUDA_PACKAGES = "nvcc", "visual_studio_integration", "cublas", "cublas_dev", "cudart", "cusolver", "cusolver_dev", "cusparse", "cusparse_dev", "npp", "npp_dev", "nvtx", "thrust" + $CUDA_PACKAGES = "nvcc", "crt", "visual_studio_integration", "cublas", "cublas_dev", "cudart", "cusolver", "cusolver_dev", "cusparse", "cusparse_dev", "npp", "npp_dev", "nvtx", "thrust" $CUDA_PACKAGES.ForEach({ $CUDA_INSTALL_ARGS += " $($_)_$($CUDA_VER)" }) # Download and install CUDA echo "Downloading CUDA installer from $CUDA_URL" @@ -112,6 +112,10 @@ jobs: if ( '${{ matrix.BUILD_CUDA_MODULE }}' -eq 'ON' ) { # python -m pip install -r open3d_ml/requirements-torch-cuda.txt python -m pip install torch torchvision --index-url https://download.pytorch.org/whl/cu126 + if ($LASTEXITCODE -ne 0) { + Write-Host "Stable PyTorch with CUDA 12.6 not found, trying nightly..." + python -m pip install --pre torch torchvision --index-url https://download.pytorch.org/whl/nightly/cu132 + } } else { python -m pip install -r open3d_ml/requirements-torch.txt } diff --git a/CHANGELOG.md b/CHANGELOG.md index cdf555b0d11..35eef6b54be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,10 @@ - macOS x86_64 not longer supported, only macOS arm64 is supported. - Python 3.13+3.14 support - Fix Windows build failure for PyTorch ops due to PyTorch's bundled fmt (v11+) requiring `/utf-8` with MSVC (PR #7447) +- Upgrade CUDA to 12.6 and PyTorch to 2.12 +- Add SBSA (ARM64) CUDA wheel builds in CI +- Refactor CI release upload steps into a reusable `update_release.sh` script +- Fix style workflow to push formatting commits to the correct PR branch ## 0.13 diff --git a/docker/Dockerfile.wheel b/docker/Dockerfile.wheel index afbc45be5cb..f471a78abd4 100644 --- a/docker/Dockerfile.wheel +++ b/docker/Dockerfile.wheel @@ -1,5 +1,5 @@ # FROM must be called before other ARGS except for ARG BASE_IMAGE -ARG BASE_IMAGE=nvidia/cuda:12.6.3-cudnn-devel-ubuntu22.04 +ARG BASE_IMAGE=nvidia/cuda:12.6.0-cudnn-devel-ubuntu22.04 FROM ${BASE_IMAGE} # Customizable build arguments from cuda.yml @@ -7,6 +7,7 @@ ARG DEVELOPER_BUILD ARG CCACHE_TAR_NAME ARG CMAKE_VERSION ARG PYTHON_VERSION +ARG BUILD_CUDA_MODULE=OFF ARG BUILD_TENSORFLOW_OPS ARG BUILD_PYTORCH_OPS ARG CI @@ -17,6 +18,7 @@ ENV DEVELOPER_BUILD=${DEVELOPER_BUILD} ENV CCACHE_TAR_NAME=${CCACHE_TAR_NAME} ENV CMAKE_VERSION=${CMAKE_VERSION} ENV PYTHON_VERSION=${PYTHON_VERSION} +ENV BUILD_CUDA_MODULE=${BUILD_CUDA_MODULE} ENV BUILD_PYTORCH_OPS=${BUILD_PYTORCH_OPS} ENV BUILD_TENSORFLOW_OPS=${BUILD_TENSORFLOW_OPS} @@ -27,14 +29,16 @@ ENV SUDO=command SHELL ["/bin/bash", "-c"] -# Fix Nvidia repo key rotation issue +# Fix Nvidia repo key rotation issue (x86_64 only — ARM CUDA images are unaffected) # https://forums.developer.nvidia.com/t/notice-cuda-linux-repository-key-rotation/212771 # https://forums.developer.nvidia.com/t/18-04-cuda-docker-image-is-broken/212892/10 # https://code.visualstudio.com/remote/advancedcontainers/reduce-docker-warnings#:~:text=Warning%3A%20apt%2Dkey%20output%20should,not%20running%20from%20a%20terminal. RUN export APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn \ - && apt-key del 7fa2af80 \ - && apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/3bf863cc.pub \ - && apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/7fa2af80.pub + && if [ "$(uname -m)" = "x86_64" ]; then \ + apt-key del 7fa2af80 \ + && apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/3bf863cc.pub \ + && apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/7fa2af80.pub; \ + fi # Dependencies: basic RUN apt-get update && apt-get install -y \ diff --git a/docker/docker_build.sh b/docker/docker_build.sh index 3eb2c188c3a..be5a2fd7e61 100755 --- a/docker/docker_build.sh +++ b/docker/docker_build.sh @@ -62,7 +62,9 @@ OPTION: 3-ml-shared-jammy : CUDA CI, 3-ml-shared-jammy (cxx11_abi), developer mode 5-ml-noble : CUDA CI, 5-ml-noble, developer mode - # CUDA wheels (Dockerfile.wheel) + # CUDA wheels — x86_64 and SBSA/ARM64 (Dockerfile.wheel) + # Architecture is auto-detected via uname -m. The same commands work on + # both x86_64 and aarch64 (SBSA) hosts. cuda_wheel_py310_dev : CUDA Python 3.10 wheel, developer mode cuda_wheel_py311_dev : CUDA Python 3.11 wheel, developer mode cuda_wheel_py312_dev : CUDA Python 3.12 wheel, developer mode @@ -80,9 +82,9 @@ HOST_OPEN3D_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. >/dev/null 2>&1 && pw # Shared variables AARCH="$(uname -m)" # do cmake pending on the architecture -CMAKE_VERSION=cmake-3.31.8-linux-${AARCH} -CUDA_VERSION=12.6.3-cudnn -CUDA_VERSION_LATEST=12.6.3-cudnn +CMAKE_VERSION=cmake-3.31.10-linux-${AARCH} +CUDA_VERSION=12.6.0-cudnn +CUDA_VERSION_LATEST=12.6.0-cudnn print_usage_and_exit_docker_build() { echo "$__usage_docker_build" @@ -176,7 +178,11 @@ openblas_build() { cuda_wheel_build() { BASE_IMAGE=nvidia/cuda:${CUDA_VERSION}-devel-ubuntu22.04 - CCACHE_TAR_NAME=open3d-ubuntu-2204-cuda-ci-ccache + if [ "${AARCH}" = "aarch64" ]; then + CCACHE_TAR_NAME=open3d-ubuntu-2204-cuda-sbsa-ci-ccache + else + CCACHE_TAR_NAME=open3d-ubuntu-2204-cuda-ci-ccache + fi options="$(echo "$@" | tr ' ' '|')" echo "[cuda_wheel_build()] options: ${options}" @@ -211,6 +217,7 @@ cuda_wheel_build() { --build-arg CCACHE_TAR_NAME="${CCACHE_TAR_NAME}" \ --build-arg CMAKE_VERSION="${CMAKE_VERSION}" \ --build-arg PYTHON_VERSION="${PYTHON_VERSION}" \ + --build-arg BUILD_CUDA_MODULE="${BUILD_CUDA_MODULE:?'env var must be set.'}" \ --build-arg BUILD_TENSORFLOW_OPS="${BUILD_TENSORFLOW_OPS}" \ --build-arg BUILD_PYTORCH_OPS="${BUILD_PYTORCH_OPS}" \ --build-arg CI="${CI:-}" \ diff --git a/python/setup.py b/python/setup.py index 5dbce75297d..d8a283ce119 100644 --- a/python/setup.py +++ b/python/setup.py @@ -151,11 +151,11 @@ def finalize_options(self): name = "@PYPI_PACKAGE_NAME@" with open("README.rst") as readme: long_description = readme.read() -# open3d-cpu wheel for Linux x86_64 +# open3d-cpu wheel for Linux (x86_64 and aarch64/SBSA) if "@BUILD_CUDA_MODULE@" == "ON": classifiers.append("Environment :: GPU :: NVIDIA CUDA") elif (sys.platform.startswith("linux") and - platform.machine() in ("i386", "x86_64", "AMD64") and + platform.machine() in ("i386", "x86_64", "AMD64", "aarch64") and "@BUILD_SYCL_MODULE@" == "OFF"): name += "-cpu" long_description += ("\n\nThis wheel only contains CPU functionality. " diff --git a/util/ci_utils.sh b/util/ci_utils.sh index 092ae3e103a..3b678133df9 100644 --- a/util/ci_utils.sh +++ b/util/ci_utils.sh @@ -30,8 +30,9 @@ BUILD_SYCL_MODULE=${BUILD_SYCL_MODULE:-OFF} TENSORFLOW_VER="2.20.0" TORCH_VER="2.10" TORCH_REPO_URL="https://download.pytorch.org/whl/torch/" +TORCH_NIGHTLY_INDEX_URL="https://download.pytorch.org/whl/nightly" # Python -PIP_VER="25.3" +PIP_VER="26.0.1" PROTOBUF_VER="6.31.1" OPEN3D_INSTALL_DIR=~/open3d_install @@ -51,6 +52,7 @@ install_python_dependencies() { TF_ARCH_DISABLE_NAME=tensorflow-cpu CUDA_VER=$(nvcc --version | grep "release " | cut -c33-37 | sed 's|[^0-9]||g') # e.g.: 117, 118, 121, ... TORCH_GLNX="torch==${TORCH_VER}+cu${CUDA_VER}" + TORCH_NIGHTLY_INDEX="${TORCH_NIGHTLY_INDEX_URL}/cu${CUDA_VER}" else # tensorflow-cpu wheels for macOS arm64 are not available if [[ "$OSTYPE" == "darwin"* ]]; then @@ -61,6 +63,7 @@ install_python_dependencies() { TF_ARCH_DISABLE_NAME=tensorflow fi TORCH_GLNX="torch==${TORCH_VER}+cpu" + TORCH_NIGHTLY_INDEX="${TORCH_NIGHTLY_INDEX_URL}/cpu" fi python -m pip install -r "${OPEN3D_SOURCE_ROOT}/python/requirements.txt" @@ -76,10 +79,17 @@ install_python_dependencies() { fi if [ "$BUILD_PYTORCH_OPS" == "ON" ]; then # ML/requirements-torch.txt if [[ "$OSTYPE" == "linux-gnu"* ]]; then - python -m pip install -U "${TORCH_GLNX}" -f "$TORCH_REPO_URL" + python -m pip install -U "${TORCH_GLNX}" -f "$TORCH_REPO_URL" || { + echo "PyTorch ${TORCH_GLNX} not found in stable index, trying nightly..." + python -m pip install --pre -U torch --index-url "$TORCH_NIGHTLY_INDEX" + } python -m pip install tensorboard elif [[ "$OSTYPE" == "darwin"* ]]; then - python -m pip install -U torch=="$TORCH_VER" -f "$TORCH_REPO_URL" tensorboard + python -m pip install -U torch=="$TORCH_VER" -f "$TORCH_REPO_URL" || { + echo "PyTorch ${TORCH_VER} not found in stable index, trying nightly..." + python -m pip install --pre -U torch --index-url "$TORCH_NIGHTLY_INDEX" + } + python -m pip install tensorboard else echo "unknown OS $OSTYPE" exit 1 @@ -169,12 +179,16 @@ build_pip_package() { echo "Azure Kinect disabled in Python wheel." BUILD_AZURE_KINECT=OFF fi - if [[ "build_jupyter" =~ ^($options)$ ]]; then + if [[ "build_jupyter" =~ ^($options)$ ]] && [[ "$AARCH" != "aarch64" ]]; then echo "Building Jupyter extension in Python wheel." BUILD_JUPYTER_EXTENSION=ON BUILD_WEBRTC_FROM_SOURCE=ON else - echo "Jupyter extension disabled in Python wheel." + if [[ "$AARCH" == "aarch64" ]] && [[ "build_jupyter" =~ ^($options)$ ]]; then + echo "Jupyter extension not supported on ARM Linux (WebRTC unavailable). Disabling." + else + echo "Jupyter extension disabled in Python wheel." + fi BUILD_JUPYTER_EXTENSION=OFF BUILD_WEBRTC_FROM_SOURCE=OFF fi