From d11304a7d094bdc7f5393ce80b51c6f605616077 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sat, 19 Sep 2026 20:53:42 +0000 Subject: [PATCH 1/7] paddlepaddle: Add version 3.3.1 Paddle has no riscv64 support at all -- there is not one "riscv" string in the v3.3.1 tree -- but nothing in it is architecturally x86-only either. WITH_ARM, WITH_SW, WITH_MIPS and WITH_LOONGARCH already switch off Xbyak's x86 JIT assembler, MKL and AVX and route the affected kernels through their scalar fallbacks, and upstream ships linux_aarch64 wheels built that way. This adds a fourth such architecture. Three patches: a WITH_RISCV option mirroring WITH_LOONGARCH (plus -latomic and no -m64), PADDLE_WITH_RISCV added to the four x86-intrinsic gates that pick their branch by listing non-x86 architectures, and a source build of Reference-LAPACK because upstream's prebuilt lapack_lnx tarball is x86-64 only -- the released linux_aarch64 wheel ships x86-64 liblapack.so.3/libblas.so.3/libgfortran.so.3 today. Everything else auto-disables: WITH_MKL and WITH_AVX default to ${AVX_FOUND}, WITH_ONEDNN needs AVX2, the AVX-512 fusion kernels are dropped from the build without AVX512F_FOUND, and CINN/CUDA/ROCm/XPU are off by default. --- .github/workflows/build-paddlepaddle.yml | 244 ++++++++++++++++++ docs/packages/paddlepaddle.yaml | 5 + .../0001-Add-a-WITH_RISCV-build-option.patch | 95 +++++++ ...6-CPUID-and-SSE-AVX-paths-on-riscv64.patch | 140 ++++++++++ ...erence-LAPACK-from-source-on-riscv64.patch | 86 ++++++ 5 files changed, 570 insertions(+) create mode 100644 .github/workflows/build-paddlepaddle.yml create mode 100644 docs/packages/paddlepaddle.yaml create mode 100644 patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch create mode 100644 patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch create mode 100644 patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch diff --git a/.github/workflows/build-paddlepaddle.yml b/.github/workflows/build-paddlepaddle.yml new file mode 100644 index 00000000000..ca375f6f43b --- /dev/null +++ b/.github/workflows/build-paddlepaddle.yml @@ -0,0 +1,244 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Paddle publishes no wheel workflow on GitHub; ci/run_setup.sh is the script +# its own CI drives, so this mirrors that script's Linux CPU environment and +# its `python setup.py bdist_wheel` invocation, narrowed to riscv64. +name: Build paddlepaddle wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/paddlepaddle.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-paddlepaddle.yml' + - 'docs/packages/paddlepaddle.yaml' + - 'patches/paddlepaddle/**' + push: + branches: [main] + paths: + - '.github/workflows/build-paddlepaddle.yml' + - 'docs/packages/paddlepaddle.yaml' + - 'patches/paddlepaddle/**' + +run-name: build-paddlepaddle ${{ inputs.version && format('- {0}', inputs.version) || '' }} + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: paddlepaddle + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build paddlepaddle ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 2880 # 48h: 1.3M lines of heavily templated C++ plus the + # third_party world, on the same 4-core runners that + # need this budget for build-vtk.yml. + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + # libpaddle.so links CPython directly, so every interpreter rebuilds the + # whole tree. cp313 is the newest upstream publishes for this release. + python: ["cp312", "cp313"] + + env: + PADDLE_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout Paddle v${{ matrix.version }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: PaddlePaddle/Paddle + ref: v${{ matrix.version }} + path: Paddle + # `git submodule update --init`, as ci/run_setup.sh runs it: cmake + # skips its own submodule step under WITH_SETUP_INSTALL. + submodules: true + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Patch Paddle source + working-directory: Paddle + run: | + git apply ../python-wheels/patches/paddlepaddle/${{ matrix.version }}/*.patch + + # Same OOM guard build-vtk.yml needs on these 4-core runners: linking + # libpaddle.so and libphi_core.so peaks well above the runner's RAM. + - name: Set swap space + uses: pierotofy/set-swap-space@fc79b3f67fa8a838184ce84a674ca12238d2c761 # master + with: + swap-size-gb: 10 + + - name: Write container script + run: | + cat > Paddle/riscv64-build-and-test.sh <<'EOF' + #!/bin/bash + set -e -x + + python_exe="/opt/python/${PYTHON_TAG}-${PYTHON_TAG}/bin/python" + py_version="${PYTHON_TAG#cp}" + py_version="${py_version:0:1}.${py_version:1}" + + case "$1" in + build) + "${python_exe}" -m pip install -U pip setuptools wheel + "${python_exe}" -m pip install -r /paddle/python/requirements.txt + "${python_exe}" -m pip install -r /paddle/paddle/scripts/compile_requirements.txt + # The operator generators under paddle/fluid/operators/generator/ + # import yaml, which upstream's own build image preinstalls rather + # than declaring in either requirements file. + "${python_exe}" -m pip install pyyaml + + export PYTHON_EXECUTABLE="${python_exe}" + export PY_VERSION="${py_version}" + export CMAKE_BUILD_TYPE=Release + export WITH_RISCV=ON + export WITH_GPU=OFF + export WITH_ROCM=OFF + export WITH_XPU=OFF + export WITH_IPU=OFF + export WITH_TENSORRT=OFF + export WITH_OPENVINO=OFF + export WITH_ONNXRUNTIME=OFF + export WITH_CUDNN_FRONTEND=OFF + export WITH_CINN=OFF + export WITH_DISTRIBUTE=OFF + export WITH_PYTHON=ON + export WITH_TESTING=OFF + export WITH_CPP_TEST=OFF + export WITH_INFERENCE_API_TEST=OFF + export ON_INFER=OFF + export WITH_STRIP=ON + # The released Linux wheels split phi and pir out of libpaddle.so; + # a single object would not link in this runner's memory. + export WITH_SHARED_PHI=ON + export WITH_SHARED_IR=ON + export MAX_JOBS="$(nproc)" + + cd /paddle + "${python_exe}" setup.py bdist_wheel + + auditwheel show dist/*.whl + auditwheel repair -w /paddle/wheelhouse dist/*.whl + ;; + test) + "${python_exe}" -m venv /tmp/venv + . /tmp/venv/bin/activate + pip install -U pip + pip install /paddle/wheelhouse/*.whl + cd /tmp + # Upstream's documented post-install verification. + python -c "import paddle; paddle.utils.run_check()" + # Exercises the LAPACK backend patch 0003 builds from source. + python -c "import paddle; x = paddle.rand([8, 8]); q, r = paddle.linalg.qr(x); assert paddle.allclose(q @ r, x, atol=1e-5)" + ;; + *) + echo "usage: $0 " >&2 + exit 1 + ;; + esac + EOF + + - name: Build wheel + run: | + podman run -t \ + --log-driver=none \ + --network=host \ + -v "${PWD}/Paddle":/paddle \ + --workdir /paddle \ + -e PYTHON_TAG="${{ matrix.python }}" \ + -e PADDLE_VERSION="${PADDLE_VERSION}" \ + --pull=newer \ + "${MANYLINUX_RISCV64_IMAGE}" \ + bash /paddle/riscv64-build-and-test.sh build + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: paddlepaddle-${{ env.PADDLE_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: Paddle/wheelhouse/*.whl + if-no-files-found: error + + - name: Test wheel + run: | + podman run -t \ + --log-driver=none \ + --network=host \ + -v "${PWD}/Paddle":/paddle \ + --workdir /paddle \ + -e PYTHON_TAG="${{ matrix.python }}" \ + -e PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ \ + "${MANYLINUX_RISCV64_IMAGE}" \ + bash /paddle/riscv64-build-and-test.sh test + + gpl_sources: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + name: Collect GPL sources (gcc) for paddlepaddle ${{ matrix.version }} + runs-on: ubuntu-24.04-riscv + env: + PADDLE_VERSION: ${{ matrix.version }} + + steps: + # setup.py copies GFORTRAN_LIB and GNU_RT_LIB_1 into paddle/libs/, which + # patch 0003 resolves to the image's own libgfortran.so.5 and + # libquadmath.so.0. + - name: Collect gcc source RPM from manylinux_riscv64 + uses: riseproject-dev/python-wheels/actions/collect-gpl-sources@main + with: + image: ${{ env.MANYLINUX_RISCV64_IMAGE }} + packages: gcc + output: gpl-sources.tar + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: paddlepaddle-${{ env.PADDLE_VERSION }}-gpl-sources + path: gpl-sources.tar + if-no-files-found: error + + publish: + name: Publish paddlepaddle ${{ matrix.version }} + needs: [setup, build_wheels, gpl_sources] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: paddlepaddle-${{ matrix.version }}-*-manylinux_riscv64 + gpl-sources-artifact: paddlepaddle-${{ matrix.version }}-gpl-sources + gpl-sources-description: gcc diff --git a/docs/packages/paddlepaddle.yaml b/docs/packages/paddlepaddle.yaml new file mode 100644 index 00000000000..bd00fd88243 --- /dev/null +++ b/docs/packages/paddlepaddle.yaml @@ -0,0 +1,5 @@ +package-name: paddlepaddle +source-code: https://github.com/PaddlePaddle/Paddle +license: Apache-2.0 +versions: +- version: 3.3.1 diff --git a/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch new file mode 100644 index 00000000000..ae6cbdb9c25 --- /dev/null +++ b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch @@ -0,0 +1,95 @@ +From 0000000000000000000000000000000000000001 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 19 Sep 2026 00:00:00 +0000 +Subject: [PATCH 1/3] Add a WITH_RISCV build option + +riscv64 is the first architecture Paddle's CMake knows nothing about: +WITH_ARM, WITH_SW, WITH_MIPS and WITH_LOONGARCH each turn off the +x86-only pieces (Xbyak's x86 JIT assembler, MKL, AVX) and define a +PADDLE_WITH_ macro the C++ tree tests, but there is no equivalent +for riscv64, so a riscv64 build takes every x86 branch. + +WITH_RISCV mirrors the WITH_LOONGARCH block, plus three riscv64-specific +additions: + + - WITH_SLEEF=OFF. Paddle only reaches SLEEF through AVX code paths + (paddle/phi/kernels/funcs/sleef_vectorized_math.h gates every use on + __AVX__/__AVX2__/__AVX512F__), so building it buys nothing here. + + - -latomic on the link lines. riscv64 has no inline instructions for + 1- and 2-byte atomics, so GCC emits libatomic calls; without this + libpaddle.so fails to load with "undefined symbol: + __atomic_exchange_1", as reported for a native riscv64 build in + PaddlePaddle/Paddle#62037. + + - cmake/flags.cmake's unconditional -m64, which riscv64 GCC rejects + ("unrecognized command line option '-m64'"), gated the same way the + other non-x86 architectures already gate it. + +Upstream-Status: To upstream + +Paddle builds linux_aarch64 wheels from WITH_ARM but has no riscv64 CI +to validate a WITH_RISCV option against, so submitting it upstream needs +a riscv64 build running there first. + +Signed-off-by: RISE Project CI +--- + CMakeLists.txt | 21 +++++++++++++++++++++ + cmake/flags.cmake | 3 ++- + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a07b810..884b37d 100755 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -330,6 +330,7 @@ option(WITH_ARM "Compile PaddlePaddle with arm support" OFF) + option(WITH_SW "Compile PaddlePaddle with sw support" OFF) + option(WITH_MIPS "Compile PaddlePaddle with mips support" OFF) + option(WITH_LOONGARCH "Compile PaddlePaddle with loongarch support" OFF) ++option(WITH_RISCV "Compile PaddlePaddle with riscv support" OFF) + option(WITH_MUSL "Compile with musl libc instead of glibc" OFF) + option(WITH_UNITY_BUILD "Compile with UnityBuild mode" OFF) + option(WITH_STRIP "Strip so files of Whl packages" OFF) +@@ -684,6 +685,26 @@ if(WITH_LOONGARCH) + add_definitions(-DPADDLE_WITH_LOONGARCH) + endif() + ++if(WITH_RISCV) ++ set(WITH_XBYAK ++ OFF ++ CACHE STRING "Disable XBYAK when compiling WITH_RISCV=ON" FORCE) ++ set(WITH_MKL ++ OFF ++ CACHE STRING "Disable MKL when compiling WITH_RISCV=ON." FORCE) ++ set(WITH_AVX ++ OFF ++ CACHE STRING "Disable AVX when compiling WITH_RISCV=ON." FORCE) ++ set(WITH_SLEEF ++ OFF ++ CACHE STRING "Disable SLEEF when compiling WITH_RISCV=ON." FORCE) ++ # riscv64 has no inline instructions for sub-word atomics, so GCC emits calls ++ # into libatomic that are otherwise left undefined in libpaddle.so. ++ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -latomic") ++ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -latomic") ++ add_definitions(-DPADDLE_WITH_RISCV) ++endif() ++ + if(WITH_ONEMKL) + add_definitions(-DPADDLE_WITH_ONEMKL) + endif() +diff --git a/cmake/flags.cmake b/cmake/flags.cmake +index 67269aa..f86b569 100644 +--- a/cmake/flags.cmake ++++ b/cmake/flags.cmake +@@ -225,7 +225,8 @@ if(NOT WIN32) + AND NOT WITH_ARM + AND NOT WITH_SW + AND NOT WITH_MIPS +- AND NOT WITH_LOONGARCH) ++ AND NOT WITH_LOONGARCH ++ AND NOT WITH_RISCV) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") + endif() + endif() +-- +2.51.0 diff --git a/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch b/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch new file mode 100644 index 00000000000..66b414c9648 --- /dev/null +++ b/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000002 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 19 Sep 2026 00:00:00 +0000 +Subject: [PATCH 2/3] Guard the x86 CPUID and SSE/AVX paths on riscv64 + +Four places select x86 intrinsics by listing every non-x86 architecture +Paddle knows about rather than by testing for x86, so any architecture +outside that list -- riscv64 here -- falls into the x86 branch and fails +to compile on / / : + + - paddle/phi/backends/cpu/cpu_info.{h,cc}: the __cpuid_count() helper + and MayIUse()'s CPUID feature probe. + - paddle/phi/core/platform/denormal.cc: DENORM_USE_INTRINSICS, which + pulls in for _MM_SET_FLUSH_ZERO_MODE. + - paddle/phi/kernels/funcs/search_compute.h: the include, + the AVX/SSE helper macros, and axpy()/axpy_noadd()'s architecture + cascade, whose non-x86 branch raises Unimplemented. + +Add PADDLE_WITH_RISCV to each list, in the same form the existing +entries use. The x86 intrinsics files that are *not* touched here are +already correct: paddle/phi/common/float16.h and both spin_lock.h copies +test __x86_64__/__i386__ directly, and the three +kernels/fusion/cpu/*avx* sources are dropped from the build when +AVX512F_FOUND is false. + +Upstream-Status: To upstream + +Same reason as patch 1/2: no riscv64 CI upstream to validate against +yet. + +Signed-off-by: RISE Project CI +--- + paddle/phi/backends/cpu/cpu_info.cc | 6 +++--- + paddle/phi/backends/cpu/cpu_info.h | 6 +++--- + paddle/phi/core/platform/denormal.cc | 3 ++- + paddle/phi/kernels/funcs/search_compute.h | 20 ++++++++++++-------- + 4 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/paddle/phi/backends/cpu/cpu_info.cc b/paddle/phi/backends/cpu/cpu_info.cc +index 3c492aa..ee93824 100644 +--- a/paddle/phi/backends/cpu/cpu_info.cc ++++ b/paddle/phi/backends/cpu/cpu_info.cc +@@ -149,9 +149,9 @@ bool MayIUse(const cpu_isa_t cpu_isa) { + if (cpu_isa == isa_any) { + return true; + } else { +-#if !defined(WITH_NV_JETSON) && !defined(PADDLE_WITH_ARM) && \ +- !defined(PADDLE_WITH_SW) && !defined(PADDLE_WITH_MIPS) && \ +- !defined(PADDLE_WITH_LOONGARCH) ++#if !defined(WITH_NV_JETSON) && !defined(PADDLE_WITH_ARM) && \ ++ !defined(PADDLE_WITH_SW) && !defined(PADDLE_WITH_MIPS) && \ ++ !defined(PADDLE_WITH_LOONGARCH) && !defined(PADDLE_WITH_RISCV) + std::array reg; + cpuid(reg.data(), 0); + int nIds = reg[0]; +diff --git a/paddle/phi/backends/cpu/cpu_info.h b/paddle/phi/backends/cpu/cpu_info.h +index 2feb294..4c2567e 100644 +--- a/paddle/phi/backends/cpu/cpu_info.h ++++ b/paddle/phi/backends/cpu/cpu_info.h +@@ -40,9 +40,9 @@ + #ifdef _WIN32 + #define cpuid(reg, x) __cpuidex(reg, x, 0) + #else +-#if !defined(WITH_NV_JETSON) && !defined(PADDLE_WITH_ARM) && \ +- !defined(PADDLE_WITH_SW) && !defined(PADDLE_WITH_MIPS) && \ +- !defined(PADDLE_WITH_LOONGARCH) ++#if !defined(WITH_NV_JETSON) && !defined(PADDLE_WITH_ARM) && \ ++ !defined(PADDLE_WITH_SW) && !defined(PADDLE_WITH_MIPS) && \ ++ !defined(PADDLE_WITH_LOONGARCH) && !defined(PADDLE_WITH_RISCV) + #include + inline void cpuid(int reg[4], int x) { + __cpuid_count(x, 0, reg[0], reg[1], reg[2], reg[3]); +diff --git a/paddle/phi/core/platform/denormal.cc b/paddle/phi/core/platform/denormal.cc +index 93c55e8..7b9e79c 100644 +--- a/paddle/phi/core/platform/denormal.cc ++++ b/paddle/phi/core/platform/denormal.cc +@@ -30,7 +30,8 @@ + + #if !defined(GCC_WITHOUT_INTRINSICS) && !defined(PADDLE_WITH_ARM) && \ + !defined(PADDLE_WITH_SW) && !defined(PADDLE_WITH_MIPS) && \ +- !defined(_WIN32) && !defined(PADDLE_WITH_LOONGARCH) ++ !defined(_WIN32) && !defined(PADDLE_WITH_LOONGARCH) && \ ++ !defined(PADDLE_WITH_RISCV) + #define DENORM_USE_INTRINSICS + #endif + +diff --git a/paddle/phi/kernels/funcs/search_compute.h b/paddle/phi/kernels/funcs/search_compute.h +index dbbd42c..3906dc0 100644 +--- a/paddle/phi/kernels/funcs/search_compute.h ++++ b/paddle/phi/kernels/funcs/search_compute.h +@@ -14,8 +14,9 @@ + + #pragma once + +-#if !defined(PADDLE_WITH_ARM) && !defined(PADDLE_WITH_SW) && \ +- !defined(PADDLE_WITH_MIPS) && !defined(PADDLE_WITH_LOONGARCH) ++#if !defined(PADDLE_WITH_ARM) && !defined(PADDLE_WITH_SW) && \ ++ !defined(PADDLE_WITH_MIPS) && !defined(PADDLE_WITH_LOONGARCH) && \ ++ !defined(PADDLE_WITH_RISCV) + #include + #endif + #include +@@ -100,8 +101,9 @@ void call_gemm_batched(const Context& dev_ctx, + } + } + +-#if !defined(PADDLE_WITH_ARM) && !defined(PADDLE_WITH_SW) && \ +- !defined(PADDLE_WITH_MIPS) && !defined(PADDLE_WITH_LOONGARCH) ++#if !defined(PADDLE_WITH_ARM) && !defined(PADDLE_WITH_SW) && \ ++ !defined(PADDLE_WITH_MIPS) && !defined(PADDLE_WITH_LOONGARCH) && \ ++ !defined(PADDLE_WITH_RISCV) + + #define __m256x __m256 + +@@ -141,8 +143,9 @@ inline void axpy(const T* x, T* y, size_t len, const T alpha) { + _mm256_add_px(_mm256_load_px(y + jjj), + _mm256_mul_px(mm_alpha, _mm256_load_px(x + jjj)))); + } +-#elif defined(PADDLE_WITH_ARM) || defined(PADDLE_WITH_SW) || \ +- defined(PADDLE_WITH_MIPS) || defined(PADDLE_WITH_LOONGARCH) ++#elif defined(PADDLE_WITH_ARM) || defined(PADDLE_WITH_SW) || \ ++ defined(PADDLE_WITH_MIPS) || defined(PADDLE_WITH_LOONGARCH) || \ ++ defined(PADDLE_WITH_RISCV) + PADDLE_THROW(common::errors::Unimplemented("axpy is not supported")); + #else + lll = len & ~SSE_CUT_LEN_MASK; +@@ -171,8 +174,9 @@ inline void axpy_noadd(const T* x, T* y, size_t len, const T alpha) { + for (jjj = 0; jjj < lll; jjj += AVX_STEP_SIZE) { + _mm256_store_px(y + jjj, _mm256_mul_px(mm_alpha, _mm256_load_px(x + jjj))); + } +-#elif defined(PADDLE_WITH_ARM) || defined(PADDLE_WITH_SW) || \ +- defined(PADDLE_WITH_MIPS) || defined(PADDLE_WITH_LOONGARCH) ++#elif defined(PADDLE_WITH_ARM) || defined(PADDLE_WITH_SW) || \ ++ defined(PADDLE_WITH_MIPS) || defined(PADDLE_WITH_LOONGARCH) || \ ++ defined(PADDLE_WITH_RISCV) + PADDLE_THROW(common::errors::Unimplemented("axpy_noadd is not supported")); + #else + lll = len & ~SSE_CUT_LEN_MASK; +-- +2.51.0 diff --git a/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch b/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch new file mode 100644 index 00000000000..a73f2f35e48 --- /dev/null +++ b/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000003 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 19 Sep 2026 00:00:00 +0000 +Subject: [PATCH 3/3] Build Reference-LAPACK from source on riscv64 + +cmake/external/lapack.cmake takes one prebuilt tarball for the whole of +Linux, lapack_lnx_v3.10.0.20210628.tar.gz on paddlepaddledeps.bj.bcebos.com, +and that tarball only ever held x86-64 binaries. Nothing links against +them -- paddle/phi/backends/dynload/lapack.cc dlopen()s liblapack.so.3 at +first use -- but setup.py copies LAPACK_LIB, BLAS_LIB, GFORTRAN_LIB and +GNU_RT_LIB_1 into paddle/libs/ unconditionally, so a non-x86 wheel ships +four x86-64 ELFs and every LAPACK-backed paddle.linalg op fails at +runtime. This is already true of the released +paddlepaddle-3.3.1-cp312-cp312-linux_aarch64.whl: its liblapack.so.3, +libblas.so.3 and libgfortran.so.3 all report "ELF 64-bit LSB shared +object, x86-64" next to a genuinely aarch64 libopenblas.so.0. + +Build the same Reference-LAPACK release (v3.10.0, what the tarball +packages) from source instead, and take libgfortran/libquadmath from the +toolchain. The comment the prebuilt tarball carries -- "lapack need +fortran compiler which many machines don't have" -- does not apply to a +manylinux build container, which ships gfortran. + +Scoped to WITH_RISCV so the x86-64 and macOS builds keep using the +tarball, but the same fix would repair the aarch64 wheel. + +Upstream-Status: To upstream + +Depends on patch 1/3's WITH_RISCV option, so it can only go upstream +together with it. + +Signed-off-by: RISE Project CI +--- + cmake/external/lapack.cmake | 37 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/cmake/external/lapack.cmake b/cmake/external/lapack.cmake +index 2865dab..25dd9b8 100644 +--- a/cmake/external/lapack.cmake ++++ b/cmake/external/lapack.cmake +@@ -20,6 +20,43 @@ set(LAPACK_DOWNLOAD_DIR + set(LAPACK_INSTALL_DIR ${THIRD_PARTY_PATH}/install/lapack) + set(LAPACK_LIB_DIR ${LAPACK_INSTALL_DIR}/lib) + ++if(WITH_RISCV) ++ # paddlepaddledeps.bj.bcebos.com only publishes the x86-64 build of ++ # lapack_lnx_v3.10.0.20210628.tar.gz, so on any other Linux architecture the ++ # block below drops four x86-64 ELFs into paddle/libs/ that ++ # phi/backends/dynload/lapack.cc can never dlopen. Build the same ++ # Reference-LAPACK release from source instead; a Fortran compiler is ++ # available here even though it isn't on the machines that note refers to. ++ set(BLAS_LIB "${LAPACK_LIB_DIR}/libblas.so.3") ++ set(LAPACK_LIB "${LAPACK_LIB_DIR}/liblapack.so.3") ++ execute_process( ++ COMMAND ${CMAKE_C_COMPILER} -print-file-name=libgfortran.so.5 ++ OUTPUT_VARIABLE GFORTRAN_LIB ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ execute_process( ++ COMMAND ${CMAKE_C_COMPILER} -print-file-name=libquadmath.so.0 ++ OUTPUT_VARIABLE GNU_RT_LIB_1 ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ ExternalProject_Add( ++ extern_lapack ++ ${EXTERNAL_PROJECT_LOG_ARGS} ++ GIT_REPOSITORY "${GIT_URL}/Reference-LAPACK/lapack.git" ++ GIT_TAG v3.10.0 ++ SOURCE_DIR ${PADDLE_SOURCE_DIR}/third_party/lapack/src ++ PREFIX ${LAPACK_PREFIX_DIR} ++ UPDATE_COMMAND "" ++ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LAPACK_INSTALL_DIR} ++ -DCMAKE_INSTALL_LIBDIR=lib ++ -DCMAKE_BUILD_TYPE=${THIRD_PARTY_BUILD_TYPE} ++ -DBUILD_SHARED_LIBS=ON ++ -DBUILD_TESTING=OFF ++ -DCBLAS=OFF ++ -DLAPACKE=OFF ++ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ++ BUILD_BYPRODUCTS ${BLAS_LIB} ${LAPACK_LIB}) ++ return() ++endif() ++ + # Note(zhouwei): lapack need fortran compiler which many machines don't have, so use precompiled library. + # use lapack tag v3.10.0 on 06/28/2021 https://github.com/Reference-LAPACK/lapack + if(LINUX) +-- +2.51.0 From b49e639416b03d127fd8fbec4278fc8d0f06b6ab Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sat, 19 Sep 2026 23:46:08 +0000 Subject: [PATCH 2/7] paddlepaddle: Resolve build-time requirements from our registry The build container ran pip without PIP_EXTRA_INDEX_URL, so python/requirements.txt resolved against public PyPI only: numpy compiled from its sdist for 21 minutes and Pillow then failed outright, since the manylinux image carries no libjpeg headers. The test container already pointed at pypi.riseproject.dev; the build one has to as well. only-binary for numpy and pillow keeps a newer PyPI release from winning the resolution and compiling from sdist once our registry lags a version behind. A dry-run resolution for cp312 and cp313 against both indexes now picks wheels for every requirement: numpy, protobuf and pillow from our registry, safetensors' own riscv64 wheel and pure-Python wheels for the rest. Also drop the swap step's OOM-guard claim: swapon fails with EINVAL on these runners because / is overlayfs (this job and a green deltalake run both report it), so the link has 15GB of RAM and no swap. --- .github/workflows/build-paddlepaddle.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-paddlepaddle.yml b/.github/workflows/build-paddlepaddle.yml index ca375f6f43b..c93fd450a76 100644 --- a/.github/workflows/build-paddlepaddle.yml +++ b/.github/workflows/build-paddlepaddle.yml @@ -87,8 +87,8 @@ jobs: run: | git apply ../python-wheels/patches/paddlepaddle/${{ matrix.version }}/*.patch - # Same OOM guard build-vtk.yml needs on these 4-core runners: linking - # libpaddle.so and libphi_core.so peaks well above the runner's RAM. + # Parity with build-vtk.yml's own guard, though swapon fails on these + # runners (/ is overlayfs), so 15GB of RAM is the real link budget. - name: Set swap space uses: pierotofy/set-swap-space@fc79b3f67fa8a838184ce84a674ca12238d2c761 # master with: @@ -164,6 +164,10 @@ jobs: esac EOF + # numpy and Pillow of python/requirements.txt have riscv64 wheels only on + # our registry; only-binary keeps a newer PyPI release from winning the + # resolution and then compiling from sdist (Pillow's needs libjpeg headers + # the image does not carry). - name: Build wheel run: | podman run -t \ @@ -173,6 +177,8 @@ jobs: --workdir /paddle \ -e PYTHON_TAG="${{ matrix.python }}" \ -e PADDLE_VERSION="${PADDLE_VERSION}" \ + -e PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ \ + -e PIP_ONLY_BINARY=numpy,pillow \ --pull=newer \ "${MANYLINUX_RISCV64_IMAGE}" \ bash /paddle/riscv64-build-and-test.sh build @@ -192,6 +198,7 @@ jobs: --workdir /paddle \ -e PYTHON_TAG="${{ matrix.python }}" \ -e PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ \ + -e PIP_ONLY_BINARY=numpy,pillow \ "${MANYLINUX_RISCV64_IMAGE}" \ bash /paddle/riscv64-build-and-test.sh test From 0e51de1f7a8d6cdee9e87a8da5b34c36de8167de Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 20 Sep 2026 00:54:35 +0000 Subject: [PATCH 3/7] paddlepaddle: Require only the Python headers to configure The cp313 build died in cmake configure, 23 minutes in, before compiling anything: Could NOT find PythonLibs (missing: PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS) (Required is at least version "3.13") cmake/external/python.cmake:21 (find_package) cmake/external/python.cmake demands a linkable libpython on every platform, and a manylinux image has none to offer: pypa/manylinux builds each of its interpreters with --disable-shared, so /opt/python/cp313-cp313 carries Python.h and libpython3.13.a but no libpython3.13.so, and FindPythonLibs does not accept a static archive. Nothing in this configuration wants the library anyway - cmake/generic.cmake's cc_library() strips `python` off the link line of every non-Windows target and links "-Wl,-undefined,dynamic_lookup" instead, leaving the CPython symbols for the interpreter that loads libpaddle.so, and the remaining PYTHON_LIBRARIES readers are the cc_test() executables (WITH_TESTING=OFF) and a pair of dead variables. Patch 0004 keeps the REQUIRED lookup on Windows and elsewhere takes the include directory from PYTHON_EXECUTABLE's own sysconfig, leaving the library optional. Satisfying find_package() by pointing PYTHON_LIBRARY at libpython3.13.a would have been the wrong repair, and an expensive one: CPython adds CFLAGSFORSHARED (-fPIC) only when LIBRARY differs from LDLIBRARY, which never holds for --disable-shared, so the archive holds no position-independent code and the link of libpaddle.so would have failed at the very end of a multi-hour build instead of at configure time. Rehearsed locally on x86_64 against the patched file with cmake, in both the branch a distro libpython takes and the branch manylinux takes (-DCMAKE_DISABLE_FIND_PACKAGE_PythonLibs): configure and generate both succeed, `python` becomes an INTERFACE target that cc_library()'s add_dependencies() edge still accepts, and a shared library built the way cc_library() builds libpaddle.so links with the Py_* symbols left undefined and no libpython in DT_NEEDED. --- .../0001-Add-a-WITH_RISCV-build-option.patch | 2 +- ...6-CPUID-and-SSE-AVX-paths-on-riscv64.patch | 2 +- ...erence-LAPACK-from-source-on-riscv64.patch | 4 +- ...Python-headers-not-a-linkable-libpyt.patch | 124 ++++++++++++++++++ 4 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch diff --git a/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch index ae6cbdb9c25..9269cb4f507 100644 --- a/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch +++ b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000001 Mon Sep 17 00:00:00 2001 From: RISE Project CI Date: Fri, 19 Sep 2026 00:00:00 +0000 -Subject: [PATCH 1/3] Add a WITH_RISCV build option +Subject: [PATCH 1/4] Add a WITH_RISCV build option riscv64 is the first architecture Paddle's CMake knows nothing about: WITH_ARM, WITH_SW, WITH_MIPS and WITH_LOONGARCH each turn off the diff --git a/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch b/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch index 66b414c9648..b4244d5618d 100644 --- a/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch +++ b/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000002 Mon Sep 17 00:00:00 2001 From: RISE Project CI Date: Fri, 19 Sep 2026 00:00:00 +0000 -Subject: [PATCH 2/3] Guard the x86 CPUID and SSE/AVX paths on riscv64 +Subject: [PATCH 2/4] Guard the x86 CPUID and SSE/AVX paths on riscv64 Four places select x86 intrinsics by listing every non-x86 architecture Paddle knows about rather than by testing for x86, so any architecture diff --git a/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch b/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch index a73f2f35e48..1132799ce61 100644 --- a/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch +++ b/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000003 Mon Sep 17 00:00:00 2001 From: RISE Project CI Date: Fri, 19 Sep 2026 00:00:00 +0000 -Subject: [PATCH 3/3] Build Reference-LAPACK from source on riscv64 +Subject: [PATCH 3/4] Build Reference-LAPACK from source on riscv64 cmake/external/lapack.cmake takes one prebuilt tarball for the whole of Linux, lapack_lnx_v3.10.0.20210628.tar.gz on paddlepaddledeps.bj.bcebos.com, @@ -26,7 +26,7 @@ tarball, but the same fix would repair the aarch64 wheel. Upstream-Status: To upstream -Depends on patch 1/3's WITH_RISCV option, so it can only go upstream +Depends on patch 1/4's WITH_RISCV option, so it can only go upstream together with it. Signed-off-by: RISE Project CI diff --git a/patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch b/patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch new file mode 100644 index 00000000000..a88de12ef5f --- /dev/null +++ b/patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000004 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Sun, 20 Sep 2026 00:00:00 +0000 +Subject: [PATCH 4/4] Require only the Python headers, not a linkable libpython + +cmake/external/python.cmake asks for a linkable libpython on every +platform: + + find_package(PythonLibs ${PY_VERSION} REQUIRED) + +but no non-Windows target ever links one. cmake/generic.cmake's +cc_library() removes `python` from the dependency list, keeps it only as +an add_dependencies() ordering edge, and links +"-Wl,-undefined,dynamic_lookup" in its place, citing pybind11's own +"Building manually" notes: libpaddle.so is an extension module, so the +interpreter that loads it is what resolves the CPython symbols. Outside +the cc_test() executables, which do embed an interpreter, nothing on +Linux consumes PYTHON_LIBRARIES at all. + +The REQUIRED therefore fails builds that would otherwise work. A CPython +configured --disable-shared installs no libpythonX.Y.so for +FindPythonLibs to find, and the module does not accept the +libpythonX.Y.a it does install, so configure stops at + + Could NOT find PythonLibs (missing: PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS) + (Required is at least version "3.13") + +before a single file compiles. Every manylinux image builds its +interpreters that way -- pypa/manylinux's build_scripts/build-cpython.sh +passes --disable-shared unconditionally -- and those images are where +release wheels get built. Pointing PYTHON_LIBRARY at the static archive +instead would only move the failure to the end of the build: CPython's +configure adds CFLAGSFORSHARED, i.e. -fPIC, only when LIBRARY differs +from LDLIBRARY, which a --disable-shared build never does, so +libpythonX.Y.a holds no position-independent code and cannot be linked +into libpaddle.so at all. + +Keep the REQUIRED lookup on Windows, where PYTHON_LIBRARIES really is +linked, and elsewhere take the include directory from the interpreter +being built against -- sysconfig's INCLUDEPY, which keeps pointing at the +real installation from inside a virtualenv -- and let the library lookup +fail harmlessly. `python` becomes a link-nothing INTERFACE target when no +library was found, because a SHARED IMPORTED target with an empty +IMPORTED_LOCATION is not valid. + +Taking the headers from PYTHON_EXECUTABLE also stops FindPythonLibs, a +module CMake 4.0 removes (policy CMP0148), from deciding which Python a +build compiles against independently of PYTHON_EXECUTABLE. + +Upstream-Status: To upstream + +Not riscv64-specific, and not specific to any one image either: manylinux +configures CPython with --disable-shared on every architecture it builds, +so the same configure failure stops an x86-64 or aarch64 build of this +release in the same place. + +Signed-off-by: RISE Project CI +--- + cmake/external/python.cmake | 45 +++++++++++++++++++++++++++++++++++--- + 1 file changed, 42 insertions(+), 3 deletions(-) + +diff --git a/cmake/external/python.cmake b/cmake/external/python.cmake +index 488540b..7e80fbb 100644 +--- a/cmake/external/python.cmake ++++ b/cmake/external/python.cmake +@@ -18,7 +18,40 @@ + + # Find Python with minimum PY_VERSION specified or will raise error! + find_package(PythonInterp ${PY_VERSION} REQUIRED) +-find_package(PythonLibs ${PY_VERSION} REQUIRED) ++ ++if(WIN32) ++ find_package(PythonLibs ${PY_VERSION} REQUIRED) ++else() ++ # cc_library() drops `python` from the link line of every non-Windows target ++ # and lets the interpreter resolve the CPython symbols when it loads the ++ # extension module (see cmake/generic.cmake), so a linkable libpython is only ++ # ever needed by the cc_test() executables that embed one -- never to build ++ # libpaddle.so. Requiring one regardless breaks the build against any CPython ++ # configured --disable-shared, as the manylinux wheel-building images are: ++ # those install no libpythonX.Y.so at all, and the libpythonX.Y.a they do ++ # install is compiled without -fPIC (configure adds CFLAGSFORSHARED only when ++ # LIBRARY differs from LDLIBRARY), so no shared object could link it either ++ # way. Take the headers from the interpreter being built against and leave the ++ # library itself optional. ++ if(NOT PYTHON_INCLUDE_DIR OR NOT EXISTS "${PYTHON_INCLUDE_DIR}/Python.h") ++ execute_process( ++ COMMAND "${PYTHON_EXECUTABLE}" "-c" ++ "import sysconfig; print(sysconfig.get_config_var('INCLUDEPY'))" ++ RESULT_VARIABLE _PYTHON_INCLUDEPY_SUCCESS ++ OUTPUT_VARIABLE _PYTHON_INCLUDEPY ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ if(NOT _PYTHON_INCLUDEPY_SUCCESS EQUAL 0 OR NOT EXISTS ++ "${_PYTHON_INCLUDEPY}/Python.h") ++ message(FATAL_ERROR "Found no Python.h for ${PYTHON_EXECUTABLE}, looked " ++ "in '${_PYTHON_INCLUDEPY}'") ++ endif() ++ set(PYTHON_INCLUDE_DIR ++ "${_PYTHON_INCLUDEPY}" ++ CACHE PATH "Path to where Python.h is found" FORCE) ++ endif() ++ find_package(PythonLibs ${PY_VERSION}) ++ set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") ++endif() + + if(WIN32) + execute_process( +@@ -64,8 +97,14 @@ + endif(WIN32) + + # Fixme: Maybe find a static library. Get SHARED/STATIC by FIND_PACKAGE. +-add_library(python SHARED IMPORTED GLOBAL) +-set_property(TARGET python PROPERTY IMPORTED_LOCATION ${PYTHON_LIBRARIES}) ++if(PYTHON_LIBRARIES) ++ add_library(python SHARED IMPORTED GLOBAL) ++ set_property(TARGET python PROPERTY IMPORTED_LOCATION ${PYTHON_LIBRARIES}) ++else() ++ # No linkable libpython: keep `python` as the link-nothing placeholder that ++ # cc_library() only ever takes an add_dependencies() ordering edge on. ++ add_library(python INTERFACE IMPORTED GLOBAL) ++endif() + + set(py_env "") + if(PYTHONINTERP_FOUND) From 2e455a23e45c8ab21bf6aa23b1042a31b64ac7ef Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 20 Sep 2026 01:54:30 +0000 Subject: [PATCH 4/7] paddlepaddle: Give OpenBLAS a riscv64 target and stop building LAPACK Run 3 of PR #2120 failed in third_party on both interpreters. extern_openblas stopped at getarch.c's "This arch/CPU is not supported by OpenBLAS": actions/checkout clones submodules without tags, so openblas.cmake's own `git checkout v0.3.28` fails and leaves the recorded submodule commit, a 0.3.7-era tree with no riscv64 target at all. Move the submodule to the tag openblas.cmake builds, and add the TARGET=RISCV64_GENERIC that OpenBLAS needs on riscv64 because getarch only reaches its riscv64 branch through -DFORCE_RISCV64_*. extern_lapack stopped at its cmake configure step, whose output EXTERNAL_PROJECT_LOG_ARGS keeps in a stamp log the job never printed. Resolve liblapack.so.3, libblas.so.3, libgfortran.so.5 and libquadmath.so.0 out of the build image instead of building Reference-LAPACK from source: nothing links against them, setup.py only copies them into paddle/libs/ for phi/backends/dynload/lapack.cc to dlopen, and a missing one now fails at configure time. Also print the stamp logs when a build fails, so the next third_party failure says why. --- .github/workflows/build-paddlepaddle.yml | 26 +++++- .../0001-Add-a-WITH_RISCV-build-option.patch | 2 +- ...6-CPUID-and-SSE-AVX-paths-on-riscv64.patch | 2 +- ...erence-LAPACK-from-source-on-riscv64.patch | 86 ------------------- ...d-libblas-from-the-build-environment.patch | 72 ++++++++++++++++ ...Python-headers-not-a-linkable-libpyt.patch | 2 +- .../0005-Give-OpenBLAS-a-riscv64-TARGET.patch | 53 ++++++++++++ 7 files changed, 152 insertions(+), 91 deletions(-) delete mode 100644 patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch create mode 100644 patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch create mode 100644 patches/paddlepaddle/3.3.1/0005-Give-OpenBLAS-a-riscv64-TARGET.patch diff --git a/.github/workflows/build-paddlepaddle.yml b/.github/workflows/build-paddlepaddle.yml index c93fd450a76..549e866bfe2 100644 --- a/.github/workflows/build-paddlepaddle.yml +++ b/.github/workflows/build-paddlepaddle.yml @@ -87,6 +87,15 @@ jobs: run: | git apply ../python-wheels/patches/paddlepaddle/${{ matrix.version }}/*.patch + # The recorded submodule commit is a 0.3.7-era tree that knows no riscv64 + # target; openblas.cmake means to move it to CBLAS_TAG itself, but its + # `git checkout v0.3.28` fails silently against a tagless submodule clone. + - name: Move the OpenBLAS submodule to the tag openblas.cmake builds + working-directory: Paddle/third_party/openblas + run: | + git fetch --depth 1 origin tag v0.3.28 + git checkout v0.3.28 + # Parity with build-vtk.yml's own guard, though swapon fails on these # runners (/ is overlayfs), so 15GB of RAM is the real link budget. - name: Set swap space @@ -106,6 +115,11 @@ jobs: case "$1" in build) + # patch 3/5 resolves LAPACK_LIB/BLAS_LIB/GFORTRAN_LIB/GNU_RT_LIB_1 + # to these, in place of an x86-64-only prebuilt tarball. + dnf install -y --setopt=install_weak_deps=False lapack blas \ + libgfortran libquadmath + "${python_exe}" -m pip install -U pip setuptools wheel "${python_exe}" -m pip install -r /paddle/python/requirements.txt "${python_exe}" -m pip install -r /paddle/paddle/scripts/compile_requirements.txt @@ -154,7 +168,7 @@ jobs: cd /tmp # Upstream's documented post-install verification. python -c "import paddle; paddle.utils.run_check()" - # Exercises the LAPACK backend patch 0003 builds from source. + # Exercises the liblapack.so.3 patch 3/5 puts in paddle/libs/. python -c "import paddle; x = paddle.rand([8, 8]); q, r = paddle.linalg.qr(x); assert paddle.allclose(q @ r, x, atol=1e-5)" ;; *) @@ -183,6 +197,14 @@ jobs: "${MANYLINUX_RISCV64_IMAGE}" \ bash /paddle/riscv64-build-and-test.sh build + # Paddle's EXTERNAL_PROJECT_LOG_ARGS sends every third_party configure and + # install step to a stamp log instead of stdout, so a failure there says + # only "Command failed: 1" in the step above. + - name: Show third_party stamp logs + if: failure() + run: | + tail -n 40 -v Paddle/build/third_party/*/src/*-stamp/*-*-*.log || true + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: paddlepaddle-${{ env.PADDLE_VERSION }}-${{ matrix.python }}-manylinux_riscv64 @@ -216,7 +238,7 @@ jobs: steps: # setup.py copies GFORTRAN_LIB and GNU_RT_LIB_1 into paddle/libs/, which - # patch 0003 resolves to the image's own libgfortran.so.5 and + # patch 3/5 resolves to the image's own libgfortran.so.5 and # libquadmath.so.0. - name: Collect gcc source RPM from manylinux_riscv64 uses: riseproject-dev/python-wheels/actions/collect-gpl-sources@main diff --git a/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch index 9269cb4f507..01b1b7e4508 100644 --- a/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch +++ b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000001 Mon Sep 17 00:00:00 2001 From: RISE Project CI Date: Fri, 19 Sep 2026 00:00:00 +0000 -Subject: [PATCH 1/4] Add a WITH_RISCV build option +Subject: [PATCH 1/5] Add a WITH_RISCV build option riscv64 is the first architecture Paddle's CMake knows nothing about: WITH_ARM, WITH_SW, WITH_MIPS and WITH_LOONGARCH each turn off the diff --git a/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch b/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch index b4244d5618d..d1b242d102a 100644 --- a/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch +++ b/patches/paddlepaddle/3.3.1/0002-Guard-the-x86-CPUID-and-SSE-AVX-paths-on-riscv64.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000002 Mon Sep 17 00:00:00 2001 From: RISE Project CI Date: Fri, 19 Sep 2026 00:00:00 +0000 -Subject: [PATCH 2/4] Guard the x86 CPUID and SSE/AVX paths on riscv64 +Subject: [PATCH 2/5] Guard the x86 CPUID and SSE/AVX paths on riscv64 Four places select x86 intrinsics by listing every non-x86 architecture Paddle knows about rather than by testing for x86, so any architecture diff --git a/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch b/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch deleted file mode 100644 index 1132799ce61..00000000000 --- a/patches/paddlepaddle/3.3.1/0003-Build-Reference-LAPACK-from-source-on-riscv64.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000003 Mon Sep 17 00:00:00 2001 -From: RISE Project CI -Date: Fri, 19 Sep 2026 00:00:00 +0000 -Subject: [PATCH 3/4] Build Reference-LAPACK from source on riscv64 - -cmake/external/lapack.cmake takes one prebuilt tarball for the whole of -Linux, lapack_lnx_v3.10.0.20210628.tar.gz on paddlepaddledeps.bj.bcebos.com, -and that tarball only ever held x86-64 binaries. Nothing links against -them -- paddle/phi/backends/dynload/lapack.cc dlopen()s liblapack.so.3 at -first use -- but setup.py copies LAPACK_LIB, BLAS_LIB, GFORTRAN_LIB and -GNU_RT_LIB_1 into paddle/libs/ unconditionally, so a non-x86 wheel ships -four x86-64 ELFs and every LAPACK-backed paddle.linalg op fails at -runtime. This is already true of the released -paddlepaddle-3.3.1-cp312-cp312-linux_aarch64.whl: its liblapack.so.3, -libblas.so.3 and libgfortran.so.3 all report "ELF 64-bit LSB shared -object, x86-64" next to a genuinely aarch64 libopenblas.so.0. - -Build the same Reference-LAPACK release (v3.10.0, what the tarball -packages) from source instead, and take libgfortran/libquadmath from the -toolchain. The comment the prebuilt tarball carries -- "lapack need -fortran compiler which many machines don't have" -- does not apply to a -manylinux build container, which ships gfortran. - -Scoped to WITH_RISCV so the x86-64 and macOS builds keep using the -tarball, but the same fix would repair the aarch64 wheel. - -Upstream-Status: To upstream - -Depends on patch 1/4's WITH_RISCV option, so it can only go upstream -together with it. - -Signed-off-by: RISE Project CI ---- - cmake/external/lapack.cmake | 37 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 37 insertions(+) - -diff --git a/cmake/external/lapack.cmake b/cmake/external/lapack.cmake -index 2865dab..25dd9b8 100644 ---- a/cmake/external/lapack.cmake -+++ b/cmake/external/lapack.cmake -@@ -20,6 +20,43 @@ set(LAPACK_DOWNLOAD_DIR - set(LAPACK_INSTALL_DIR ${THIRD_PARTY_PATH}/install/lapack) - set(LAPACK_LIB_DIR ${LAPACK_INSTALL_DIR}/lib) - -+if(WITH_RISCV) -+ # paddlepaddledeps.bj.bcebos.com only publishes the x86-64 build of -+ # lapack_lnx_v3.10.0.20210628.tar.gz, so on any other Linux architecture the -+ # block below drops four x86-64 ELFs into paddle/libs/ that -+ # phi/backends/dynload/lapack.cc can never dlopen. Build the same -+ # Reference-LAPACK release from source instead; a Fortran compiler is -+ # available here even though it isn't on the machines that note refers to. -+ set(BLAS_LIB "${LAPACK_LIB_DIR}/libblas.so.3") -+ set(LAPACK_LIB "${LAPACK_LIB_DIR}/liblapack.so.3") -+ execute_process( -+ COMMAND ${CMAKE_C_COMPILER} -print-file-name=libgfortran.so.5 -+ OUTPUT_VARIABLE GFORTRAN_LIB -+ OUTPUT_STRIP_TRAILING_WHITESPACE) -+ execute_process( -+ COMMAND ${CMAKE_C_COMPILER} -print-file-name=libquadmath.so.0 -+ OUTPUT_VARIABLE GNU_RT_LIB_1 -+ OUTPUT_STRIP_TRAILING_WHITESPACE) -+ ExternalProject_Add( -+ extern_lapack -+ ${EXTERNAL_PROJECT_LOG_ARGS} -+ GIT_REPOSITORY "${GIT_URL}/Reference-LAPACK/lapack.git" -+ GIT_TAG v3.10.0 -+ SOURCE_DIR ${PADDLE_SOURCE_DIR}/third_party/lapack/src -+ PREFIX ${LAPACK_PREFIX_DIR} -+ UPDATE_COMMAND "" -+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LAPACK_INSTALL_DIR} -+ -DCMAKE_INSTALL_LIBDIR=lib -+ -DCMAKE_BUILD_TYPE=${THIRD_PARTY_BUILD_TYPE} -+ -DBUILD_SHARED_LIBS=ON -+ -DBUILD_TESTING=OFF -+ -DCBLAS=OFF -+ -DLAPACKE=OFF -+ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -+ BUILD_BYPRODUCTS ${BLAS_LIB} ${LAPACK_LIB}) -+ return() -+endif() -+ - # Note(zhouwei): lapack need fortran compiler which many machines don't have, so use precompiled library. - # use lapack tag v3.10.0 on 06/28/2021 https://github.com/Reference-LAPACK/lapack - if(LINUX) --- -2.51.0 diff --git a/patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch b/patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch new file mode 100644 index 00000000000..01dec54bc5e --- /dev/null +++ b/patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000003 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 19 Sep 2026 00:00:00 +0000 +Subject: [PATCH 3/5] Take liblapack and libblas from the build environment + +cmake/external/lapack.cmake takes one prebuilt tarball for the whole of +Linux, lapack_lnx_v3.10.0.20210628.tar.gz on paddlepaddledeps.bj.bcebos.com, +and that tarball only ever held x86-64 binaries. Nothing links against +them -- paddle/phi/backends/dynload/lapack.cc dlopen()s liblapack.so.3 at +first use -- but setup.py copies LAPACK_LIB, BLAS_LIB, GFORTRAN_LIB and +GNU_RT_LIB_1 into paddle/libs/ unconditionally, so a non-x86 wheel ships +four x86-64 ELFs and every LAPACK-backed paddle.linalg op fails at +runtime. This is already true of the released +paddlepaddle-3.3.1-cp312-cp312-linux_aarch64.whl: its liblapack.so.3, +libblas.so.3 and libgfortran.so.3 all report "ELF 64-bit LSB shared +object, x86-64" next to a genuinely aarch64 libopenblas.so.0. + +Resolve the same four sonames out of the build environment instead, which +is where GFORTRAN_LIB and GNU_RT_LIB_1 have to come from on any +architecture the tarball does not cover, and fail at configure time +rather than at wheel-packing time when one is missing. Reference-LAPACK +is what distributions package as liblapack.so.3, so this keeps shipping +the same ABI the tarball did. + +Scoped to WITH_RISCV so the x86-64 and macOS builds keep using the +tarball, but the same fix would repair the aarch64 wheel. + +Upstream-Status: To upstream + +Depends on patch 1/5's WITH_RISCV option, so it can only go upstream +together with it. + +Signed-off-by: RISE Project CI +--- + cmake/external/lapack.cmake | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/cmake/external/lapack.cmake b/cmake/external/lapack.cmake +--- a/cmake/external/lapack.cmake ++++ b/cmake/external/lapack.cmake +@@ -20,6 +20,29 @@ set(LAPACK_DOWNLOAD_DIR + set(LAPACK_INSTALL_DIR ${THIRD_PARTY_PATH}/install/lapack) + set(LAPACK_LIB_DIR ${LAPACK_INSTALL_DIR}/lib) + ++if(WITH_RISCV) ++ # paddlepaddledeps.bj.bcebos.com publishes lapack_lnx_v3.10.0.20210628.tar.gz ++ # as an x86-64 build only, so on any other Linux architecture the block below ++ # hands setup.py four x86-64 ELFs to copy into paddle/libs/, which ++ # phi/backends/dynload/lapack.cc can then never dlopen. ++ macro(lapack_system_lib var soname) ++ execute_process( ++ COMMAND ${CMAKE_C_COMPILER} -print-file-name=${soname} ++ OUTPUT_VARIABLE ${var} ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ if(NOT IS_ABSOLUTE "${${var}}") ++ message(FATAL_ERROR "WITH_RISCV needs ${soname} on the library path") ++ endif() ++ message(STATUS "Using ${${var}} for ${var}") ++ endmacro() ++ lapack_system_lib(LAPACK_LIB liblapack.so.3) ++ lapack_system_lib(BLAS_LIB libblas.so.3) ++ lapack_system_lib(GFORTRAN_LIB libgfortran.so.5) ++ lapack_system_lib(GNU_RT_LIB_1 libquadmath.so.0) ++ add_custom_target(extern_lapack) ++ return() ++endif() ++ + # Note(zhouwei): lapack need fortran compiler which many machines don't have, so use precompiled library. + # use lapack tag v3.10.0 on 06/28/2021 https://github.com/Reference-LAPACK/lapack + if(LINUX) +-- +2.51.0 diff --git a/patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch b/patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch index a88de12ef5f..9f5cc328e42 100644 --- a/patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch +++ b/patches/paddlepaddle/3.3.1/0004-Require-only-the-Python-headers-not-a-linkable-libpyt.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000004 Mon Sep 17 00:00:00 2001 From: RISE Project CI Date: Sun, 20 Sep 2026 00:00:00 +0000 -Subject: [PATCH 4/4] Require only the Python headers, not a linkable libpython +Subject: [PATCH 4/5] Require only the Python headers, not a linkable libpython cmake/external/python.cmake asks for a linkable libpython on every platform: diff --git a/patches/paddlepaddle/3.3.1/0005-Give-OpenBLAS-a-riscv64-TARGET.patch b/patches/paddlepaddle/3.3.1/0005-Give-OpenBLAS-a-riscv64-TARGET.patch new file mode 100644 index 00000000000..1364f9b9a78 --- /dev/null +++ b/patches/paddlepaddle/3.3.1/0005-Give-OpenBLAS-a-riscv64-TARGET.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000005 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Sat, 20 Sep 2026 00:00:00 +0000 +Subject: [PATCH 5/5] Give OpenBLAS a riscv64 TARGET + +OpenBLAS cannot detect a riscv64 host: getarch.c reaches its +riscv64 branch only through -DFORCE_RISCV64_*, which Makefile.system +derives from TARGET=, so a plain `make` stops at + + getarch.c: error: #error "This arch/CPU is not supported by OpenBLAS." + +WITH_ARM already answers this with TARGET=ARMV8. Do the same for +riscv64 with TARGET=RISCV64_GENERIC, whose -march=rv64imafdc -mabi=lp64d +is the rv64gc baseline every riscv64 wheel has to run on; the vector +targets (RISCV64_ZVL128B, RISCV64_ZVL256B) would bake RVV into a +statically linked libopenblas.a. + +Upstream-Status: To upstream + +Depends on patch 1/5's WITH_RISCV option, so it can only go upstream +together with it. + +Signed-off-by: RISE Project CI +--- + cmake/external/openblas.cmake | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/cmake/external/openblas.cmake b/cmake/external/openblas.cmake +--- a/cmake/external/openblas.cmake ++++ b/cmake/external/openblas.cmake +@@ -89,15 +89,19 @@ + if(WITH_ARM) + set(ARM_ARGS TARGET=ARMV8) + endif() ++ if(WITH_RISCV) ++ set(RISCV_ARGS TARGET=RISCV64_GENERIC) ++ endif() + set(COMMON_ARGS CC=${OPENBLAS_CC} NO_SHARED=1 NO_LAPACK=1 libs) + ExternalProject_Add( + extern_openblas + ${EXTERNAL_PROJECT_LOG_ARGS} + SOURCE_DIR ${CBLAS_SOURCE_DIR} + PREFIX ${CBLAS_PREFIX_DIR} + INSTALL_DIR ${CBLAS_INSTALL_DIR} + BUILD_IN_SOURCE 1 +- BUILD_COMMAND make ${ARM_ARGS} -s -j${NPROC} ${COMMON_ARGS} ${OPTIONAL_ARGS} ++ BUILD_COMMAND make ${ARM_ARGS} ${RISCV_ARGS} -s -j${NPROC} ${COMMON_ARGS} ++ ${OPTIONAL_ARGS} + INSTALL_COMMAND make install NO_SHARED=1 NO_LAPACK=1 PREFIX= + UPDATE_COMMAND "" + CONFIGURE_COMMAND "" +-- +2.51.0 From ba04cc17170bbcd9ce4cc1debc33b22f58ac2da0 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 20 Sep 2026 02:21:19 +0000 Subject: [PATCH 5/7] paddlepaddle: Do not ask riscv64 for a libquadmath it cannot have Run 4's build container died in 30 seconds on the dnf line the previous commit added: "Error: Unable to find a match: libquadmath". libquadmath is built only where __float128 is a type distinct from long double, so GCC ships none for riscv64 and Rocky packages none - the same reason aarch64 has none. Drop it from the dnf line, where libgfortran was also redundant (already in the image, and a dependency of lapack anyway). Patch 3/5 asked for libquadmath.so.0 too, and its FATAL_ERROR would have stopped the next configure, so stop resolving GNU_RT_LIB_1 at all. That leaves it empty, which setup.py's unconditional shutil.copy() cannot take, so guard that copy the way the neighbouring GNU_RT_LIB_2 one already is - architecture-agnostically, since this is the bug on every platform without a libquadmath. Both hunks are now generated from the pristine v3.3.1 files rather than hand-written, and verified to apply; the patched setup.py parses. --- .github/workflows/build-paddlepaddle.yml | 8 +-- ...d-libblas-from-the-build-environment.patch | 65 ++++++++++++++----- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build-paddlepaddle.yml b/.github/workflows/build-paddlepaddle.yml index 549e866bfe2..13ce4448709 100644 --- a/.github/workflows/build-paddlepaddle.yml +++ b/.github/workflows/build-paddlepaddle.yml @@ -115,10 +115,10 @@ jobs: case "$1" in build) - # patch 3/5 resolves LAPACK_LIB/BLAS_LIB/GFORTRAN_LIB/GNU_RT_LIB_1 - # to these, in place of an x86-64-only prebuilt tarball. - dnf install -y --setopt=install_weak_deps=False lapack blas \ - libgfortran libquadmath + # patch 3/5 resolves LAPACK_LIB/BLAS_LIB/GFORTRAN_LIB to these, in + # place of an x86-64-only prebuilt tarball; libgfortran comes with + # them, and riscv64 has no libquadmath to ask for. + dnf install -y --setopt=install_weak_deps=False lapack blas "${python_exe}" -m pip install -U pip setuptools wheel "${python_exe}" -m pip install -r /paddle/python/requirements.txt diff --git a/patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch b/patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch index 01dec54bc5e..5ceda2cb8d3 100644 --- a/patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch +++ b/patches/paddlepaddle/3.3.1/0003-Take-liblapack-and-libblas-from-the-build-environment.patch @@ -15,37 +15,46 @@ paddlepaddle-3.3.1-cp312-cp312-linux_aarch64.whl: its liblapack.so.3, libblas.so.3 and libgfortran.so.3 all report "ELF 64-bit LSB shared object, x86-64" next to a genuinely aarch64 libopenblas.so.0. -Resolve the same four sonames out of the build environment instead, which -is where GFORTRAN_LIB and GNU_RT_LIB_1 have to come from on any -architecture the tarball does not cover, and fail at configure time -rather than at wheel-packing time when one is missing. Reference-LAPACK -is what distributions package as liblapack.so.3, so this keeps shipping -the same ABI the tarball did. +Resolve the sonames out of the build environment instead, which is where +GFORTRAN_LIB has to come from on any architecture the tarball does not +cover, and fail at configure time rather than at wheel-packing time when +one is missing. Reference-LAPACK is what distributions package as +liblapack.so.3, so this keeps shipping the same ABI the tarball did. -Scoped to WITH_RISCV so the x86-64 and macOS builds keep using the -tarball, but the same fix would repair the aarch64 wheel. +GNU_RT_LIB_1 is left unset, because libquadmath exists only where +__float128 is a type distinct from long double: GCC builds none for +riscv64 (nor for aarch64), and Rocky has no libquadmath package there at +all. setup.py copied it unconditionally, so make that copy conditional +the way the neighbouring GNU_RT_LIB_2 one already is -- not gated on any +architecture flag, since an empty GNU_RT_LIB_1 is the bug on every +platform GCC ships no libquadmath for. + +The cmake half is scoped to WITH_RISCV so the x86-64 and macOS builds +keep using the tarball, but the same fix would repair the aarch64 wheel. Upstream-Status: To upstream -Depends on patch 1/5's WITH_RISCV option, so it can only go upstream -together with it. +The cmake half depends on patch 1/5's WITH_RISCV option, so it can only +go upstream together with it; the setup.py half stands alone. Signed-off-by: RISE Project CI --- cmake/external/lapack.cmake | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) + setup.py | 9 +++++++-- + 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/cmake/external/lapack.cmake b/cmake/external/lapack.cmake --- a/cmake/external/lapack.cmake +++ b/cmake/external/lapack.cmake -@@ -20,6 +20,29 @@ set(LAPACK_DOWNLOAD_DIR +@@ -19,6 +19,29 @@ + ${PADDLE_SOURCE_DIR}/third_party/lapack/${CMAKE_SYSTEM_NAME}) set(LAPACK_INSTALL_DIR ${THIRD_PARTY_PATH}/install/lapack) set(LAPACK_LIB_DIR ${LAPACK_INSTALL_DIR}/lib) - ++ +if(WITH_RISCV) + # paddlepaddledeps.bj.bcebos.com publishes lapack_lnx_v3.10.0.20210628.tar.gz + # as an x86-64 build only, so on any other Linux architecture the block below -+ # hands setup.py four x86-64 ELFs to copy into paddle/libs/, which ++ # hands setup.py x86-64 ELFs to copy into paddle/libs/, which + # phi/backends/dynload/lapack.cc can then never dlopen. + macro(lapack_system_lib var soname) + execute_process( @@ -60,13 +69,35 @@ diff --git a/cmake/external/lapack.cmake b/cmake/external/lapack.cmake + lapack_system_lib(LAPACK_LIB liblapack.so.3) + lapack_system_lib(BLAS_LIB libblas.so.3) + lapack_system_lib(GFORTRAN_LIB libgfortran.so.5) -+ lapack_system_lib(GNU_RT_LIB_1 libquadmath.so.0) ++ # No GNU_RT_LIB_1: riscv64 GCC builds no libquadmath. + add_custom_target(extern_lapack) + return() +endif() -+ + # Note(zhouwei): lapack need fortran compiler which many machines don't have, so use precompiled library. # use lapack tag v3.10.0 on 06/28/2021 https://github.com/Reference-LAPACK/lapack - if(LINUX) +diff --git a/setup.py b/setup.py +--- a/setup.py ++++ b/setup.py +@@ -1564,12 +1564,17 @@ + os.path.basename(env_dict.get("LAPACK_LIB")), + os.path.basename(env_dict.get("BLAS_LIB")), + os.path.basename(env_dict.get("GFORTRAN_LIB")), +- os.path.basename(env_dict.get("GNU_RT_LIB_1")), + ] + shutil.copy(env_dict.get("BLAS_LIB"), libs_path) + shutil.copy(env_dict.get("LAPACK_LIB"), libs_path) + shutil.copy(env_dict.get("GFORTRAN_LIB"), libs_path) +- shutil.copy(env_dict.get("GNU_RT_LIB_1"), libs_path) ++ # libquadmath is built only where __float128 differs from long double, so ++ # there is none to ship on riscv64 or aarch64. ++ if env_dict.get("GNU_RT_LIB_1"): ++ package_data['paddle.libs'] += [ ++ os.path.basename(env_dict.get("GNU_RT_LIB_1")) ++ ] ++ shutil.copy(env_dict.get("GNU_RT_LIB_1"), libs_path) + if env_dict.get("WITH_MAGMA") == 'ON': + package_data['paddle.libs'] += [ + os.path.basename('MAGMA_LIB'), -- 2.51.0 From 70e93fb52fd270ee7ab188205f6b1ca128ce29fa Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 20 Sep 2026 03:45:41 +0000 Subject: [PATCH 6/7] paddlepaddle: Fetch the submodule tags third_party's patch steps check out Run 5 of PR #2120 got 40 minutes into third_party on both interpreters - past every round-3 and round-4 fix, which all held - and then died in the same class of bug as OpenBLAS, one dependency further on: Performing patch step for 'extern_gloo' error: pathspec 'v0.0.3' did not match any file(s) known to git gloo.cmake's PATCH_COMMAND is `git checkout -- . && git checkout ${GLOO_TAG}`, and actions/checkout gives a submodule its recorded commit without any tags, so that ref does not exist. Where openblas.cmake runs its checkout through execute_process with no RESULT_VARIABLE and silently builds the stale tree, this one is an ExternalProject patch step, so it takes the whole build down instead. third_party/gloo is recorded at 8b6b61d, which is exactly what refs/tags/v0.0.3 names, so nothing needs moving here: only the ref is missing, and a shallow tag fetch is the whole fix. Sweeping the rest of cmake/external for the same shape found one more that this configuration reaches and run 5 had not got to yet: protobuf.cmake's build_protobuf() patch step is an unconditional `cd && git checkout v21.12`, and third_party/protobuf is recorded at f0dc78d, which is refs/tags/v21.12^{}. It would have failed identically a few minutes later. Everything else is safe - eigen, warpctc, warprnnt, cccl, libxsmm and the fp8 cutlass switch name commits rather than tags, and the tag-name checkouts in pybind11, pocketfft, gtest, cub, openvino and rocksdb are gated on GCC < 9, APPLE, WITH_TESTING/WITH_DISTRIBUTE, CUDA, WITH_OPENVINO and the parameter-server tree, none of which this build reaches. Rehearsed locally for both submodules by reproducing what actions/checkout leaves behind, a repo fetched at the recorded commit with no tags: the checkout fails with run 5's exact message, the tag fetch supplies the ref, and the checkout then lands on the commit that was already there. --- .github/workflows/build-paddlepaddle.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build-paddlepaddle.yml b/.github/workflows/build-paddlepaddle.yml index 13ce4448709..48ae76fcce2 100644 --- a/.github/workflows/build-paddlepaddle.yml +++ b/.github/workflows/build-paddlepaddle.yml @@ -96,6 +96,15 @@ jobs: git fetch --depth 1 origin tag v0.3.28 git checkout v0.3.28 + # gloo.cmake and protobuf.cmake make `git checkout ` an + # ExternalProject patch step, which aborts the build against the tagless + # submodule clone; both tags already name the recorded commit, so only the + # ref is missing and no checkout of our own is needed. + - name: Fetch the submodule tags the third_party patch steps check out + run: | + git -C Paddle/third_party/gloo fetch --depth 1 origin tag v0.0.3 + git -C Paddle/third_party/protobuf fetch --depth 1 origin tag v21.12 + # Parity with build-vtk.yml's own guard, though swapon fails on these # runners (/ is overlayfs), so 15GB of RAM is the real link budget. - name: Set swap space From ed22659c34ffe42e45f9bc84e0043eb63796a645 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 20 Sep 2026 06:50:32 +0000 Subject: [PATCH 7/7] paddlepaddle: Turn SLEEF off where the switch is still read Round 6 reached Paddle's own C++ tree and stopped at 21% of phi_core, on kernels/funcs/gru_compute.cc: eight "'Sleef_sinf1_u35' was not declared in this scope" errors out of activation_functor.h's Sine/Cosine specialisations, which select the SLEEF entry points on PADDLE_WITH_SLEEF alone. Patch 1/5 already meant to keep SLEEF out of a riscv64 build, but its set(WITH_SLEEF OFF ... FORCE) sat in the WITH_RISCV block at CMakeLists.txt:686, and cmake/third_party.cmake is included at line 591 - so cmake/sleef.cmake had already run add_definitions(-DPADDLE_WITH_SLEEF) by then. The only consumer still reading the FORCE was paddle/phi/CMakeLists.txt's `if(WITH_SLEEF) list(APPEND PHI_DEPS sleef)`, leaving the build compiling the SLEEF path and not linking SLEEF. The configure log shows the result plainly: "-- Compile with Sleef support". Move the decision to upstream's own WITH_SLEEF_DEFAULT switch at CMakeLists.txt:356, next to WIN32 and WITH_ROCM, which runs before third_party is included and is reached because setup.py forwards every WITH_* environment variable as a -D, so WITH_RISCV is already in the cache. WITH_SLEEF is then consistently OFF, PADDLE_WITH_SLEEF is never defined, and Sine/Cosine fall back to libm - the configuration Paddle already ships for Windows and ROCm. It also drops the SLEEF ExternalProject, roughly 25 minutes per leg on these runners. Turning SLEEF on instead is not an option here: SLEEF 3.6.1's src/libm/CMakeLists.txt leaves DSP_SCALAR out of SLEEF_ARCH_RISCV64's header list, alone among its six architectures, and DSP_SCALAR is the only entry carrying no ISA name - the only one mkrename.c emits unsuffixed scalar declarations from. The generated riscv64 sleef.h declares Sleef_sinf1_u35purec and never Sleef_sinf1_u35. --- .../0001-Add-a-WITH_RISCV-build-option.patch | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch index 01b1b7e4508..dbb70736de3 100644 --- a/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch +++ b/patches/paddlepaddle/3.3.1/0001-Add-a-WITH_RISCV-build-option.patch @@ -12,9 +12,22 @@ for riscv64, so a riscv64 build takes every x86 branch. WITH_RISCV mirrors the WITH_LOONGARCH block, plus three riscv64-specific additions: - - WITH_SLEEF=OFF. Paddle only reaches SLEEF through AVX code paths - (paddle/phi/kernels/funcs/sleef_vectorized_math.h gates every use on - __AVX__/__AVX2__/__AVX512F__), so building it buys nothing here. + - WITH_SLEEF=OFF, set through upstream's own WITH_SLEEF_DEFAULT switch + rather than from the WITH_RISCV block, because cmake/third_party.cmake + is included at CMakeLists.txt:591, long before that block: a + set(WITH_SLEEF OFF ... FORCE) there is read too late, after + cmake/sleef.cmake has already run add_definitions(-DPADDLE_WITH_SLEEF), + and only paddle/phi/CMakeLists.txt's `if(WITH_SLEEF) list(APPEND + PHI_DEPS sleef)` still sees the OFF - compiling the SLEEF path without + linking SLEEF. SLEEF 3.6.1 cannot serve Paddle on riscv64 in any case: + src/libm/CMakeLists.txt leaves DSP_SCALAR out of SLEEF_ARCH_RISCV64's + header list, alone among the six architectures, and DSP_SCALAR is the + only entry with no ISA name, i.e. the only one mkrename.c emits the + unsuffixed scalar declarations from. The generated riscv64 sleef.h + therefore declares Sleef_sinf1_u35purec but never Sleef_sinf1_u35, + which is what paddle/phi/kernels/funcs/activation_functor.h calls + under PADDLE_WITH_SLEEF. WIN32 and WITH_ROCM already take this same + SLEEF-less configuration. - -latomic on the link lines. riscv64 has no inline instructions for 1- and 2-byte atomics, so GCC emits libatomic calls; without this @@ -34,9 +47,9 @@ a riscv64 build running there first. Signed-off-by: RISE Project CI --- - CMakeLists.txt | 21 +++++++++++++++++++++ + CMakeLists.txt | 20 +++++++++++++++++++- cmake/flags.cmake | 3 ++- - 2 files changed, 23 insertions(+), 1 deletion(-) + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a07b810..884b37d 100755 @@ -50,7 +63,14 @@ index a07b810..884b37d 100755 option(WITH_MUSL "Compile with musl libc instead of glibc" OFF) option(WITH_UNITY_BUILD "Compile with UnityBuild mode" OFF) option(WITH_STRIP "Strip so files of Whl packages" OFF) -@@ -684,6 +685,26 @@ if(WITH_LOONGARCH) +@@ -356,5 +357,5 @@ + set(WITH_SLEEF_DEFAULT ON) +-if(WIN32 OR WITH_ROCM) ++if(WIN32 OR WITH_ROCM OR WITH_RISCV) + set(WITH_SLEEF_DEFAULT OFF) + endif() + option( +@@ -684,6 +685,23 @@ if(WITH_LOONGARCH) add_definitions(-DPADDLE_WITH_LOONGARCH) endif() @@ -64,9 +84,6 @@ index a07b810..884b37d 100755 + set(WITH_AVX + OFF + CACHE STRING "Disable AVX when compiling WITH_RISCV=ON." FORCE) -+ set(WITH_SLEEF -+ OFF -+ CACHE STRING "Disable SLEEF when compiling WITH_RISCV=ON." FORCE) + # riscv64 has no inline instructions for sub-word atomics, so GCC emits calls + # into libatomic that are otherwise left undefined in libpaddle.so. + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -latomic")