From 5d821d3db1423b76c74f0085c66d7ee62251feb4 Mon Sep 17 00:00:00 2001 From: Yuval Shekel Date: Sun, 28 Jul 2024 19:27:41 +0300 Subject: [PATCH] refactor C++ examples to work with install-dir, or build from source and choose device --- .github/workflows/examples.yml | 37 +++++- examples/c++/best-practice-ntt/README.md | 8 +- examples/c++/best-practice-ntt/compile.sh | 22 ---- examples/c++/best-practice-ntt/run.sh | 65 +++++++++- examples/c++/examples_utils.h | 9 +- examples/c++/msm/README.md | 9 +- examples/c++/msm/compile.sh | 22 ---- examples/c++/msm/run.sh | 65 +++++++++- examples/c++/ntt/README.md | 9 +- examples/c++/ntt/compile.sh | 22 ---- examples/c++/ntt/run.sh | 65 +++++++++- examples/c++/pedersen-commitment/README.md | 10 +- examples/c++/pedersen-commitment/compile.sh | 22 ---- examples/c++/pedersen-commitment/run.sh | 65 +++++++++- examples/c++/polynomial-api/README.md | 7 +- examples/c++/polynomial-api/compile.sh | 22 ---- examples/c++/polynomial-api/example.cpp | 121 +++++++++--------- examples/c++/polynomial-api/run.sh | 65 +++++++++- .../c++/polynomial_multiplication/README.md | 9 +- .../c++/polynomial_multiplication/compile.sh | 22 ---- .../c++/polynomial_multiplication/example.cpp | 18 +-- examples/c++/polynomial_multiplication/run.sh | 66 +++++++++- examples/c++/risc0/README.md | 7 +- examples/c++/risc0/compile.sh | 22 ---- examples/c++/risc0/run.sh | 65 +++++++++- 25 files changed, 587 insertions(+), 267 deletions(-) delete mode 100755 examples/c++/best-practice-ntt/compile.sh delete mode 100755 examples/c++/msm/compile.sh delete mode 100755 examples/c++/ntt/compile.sh delete mode 100755 examples/c++/pedersen-commitment/compile.sh delete mode 100755 examples/c++/polynomial-api/compile.sh delete mode 100755 examples/c++/polynomial_multiplication/compile.sh delete mode 100755 examples/c++/risc0/compile.sh diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 9e418751..15ec6297 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -24,12 +24,42 @@ jobs: check-changed-files: uses: ./.github/workflows/check-changed-files.yml + extract-cuda-backend-branch: + name: Extract cuda branch name + runs-on: ubuntu-22.04 + outputs: + cuda-backend-branch: ${{ steps.extract.outputs.cuda-backend-branch }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Extract Private Branch from PR Description + id: extract + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + DESCRIPTION=$(gh pr view ${{ github.event.pull_request.number }} --json body -q '.body') + echo "PR Description: $DESCRIPTION" + CUDA_BE_BRANCH=$(echo "$DESCRIPTION" | grep -oP 'cuda-backend-branch:\s*\K[^\s]+') || true + if [ -z "$CUDA_BE_BRANCH" ]; then + CUDA_BE_BRANCH="main" # Default branch if not specified + fi + echo "Extracted CUDA Backend Branch: $CUDA_BE_BRANCH" + echo "::set-output name=cuda-backend-branch::$CUDA_BE_BRANCH" + run-examples: - runs-on: [self-hosted, Linux, X64, icicle, examples] + runs-on: [self-hosted, Linux, X64, icicle, examples, extract-cuda-backend-branch] needs: check-changed-files steps: - name: Checkout uses: actions/checkout@v4 + - name: Checkout CUDA Backend + uses: actions/checkout@v4 + with: + repository: ingonyama-zk/icicle-cuda-backend + path: ./icicle_v3/backend/cuda + token: ${{ secrets.GITHUB_TOKEN }} + ssh-key: ${{ secrets.CUDA_PULL_KEY }} + ref: ${{ needs.extract-branch.outputs.cuda-backend-branch }} - name: c++ examples working-directory: ./examples/c++ if: needs.check-changed-files.outputs.cpp_cuda == 'true' || needs.check-changed-files.outputs.examples == 'true' @@ -38,9 +68,8 @@ jobs: for dir in $(find . -mindepth 1 -maxdepth 1 -type d); do if [ -d "$dir" ]; then echo "Running command in $dir" - cd $dir - ./compile.sh - ./run.sh + cd $dir + ./run.sh -d CUDA cd - fi done diff --git a/examples/c++/best-practice-ntt/README.md b/examples/c++/best-practice-ntt/README.md index 26fbc7fc..0ba43ee2 100644 --- a/examples/c++/best-practice-ntt/README.md +++ b/examples/c++/best-practice-ntt/README.md @@ -23,11 +23,13 @@ Typically, you concurrently ## Running the example -To change the default curve BN254, edit `compile.sh` and `CMakeLists.txt` +To change the default curve BN254, edit `run.sh` and `CMakeLists.txt` ```sh -./compile.sh -./run.sh +# for CPU +./run.sh -d CPU +# for CUDA +./run.sh -d CUDA -b /path/to/cuda/backend/install/dir ``` To compare with ICICLE baseline (i.e. non-concurrent) NTT, you can run [this example](../ntt/README.md). diff --git a/examples/c++/best-practice-ntt/compile.sh b/examples/c++/best-practice-ntt/compile.sh deleted file mode 100755 index 297aae3a..00000000 --- a/examples/c++/best-practice-ntt/compile.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build/example -mkdir -p build/icicle - -ICILE_DIR=$(realpath "../../../icicle_v3/") -ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" - -# Build Icicle and the example app that links to it -if [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then - echo "building icicle with CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -DBACKEND_DIR=$(realpath "build/icicle/backend") -else - echo "building icicle without CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -fi -cmake --build build/icicle -j -cmake --build build/example -j diff --git a/examples/c++/best-practice-ntt/run.sh b/examples/c++/best-practice-ntt/run.sh index 01eca66b..23615cba 100755 --- a/examples/c++/best-practice-ntt/run.sh +++ b/examples/c++/best-practice-ntt/run.sh @@ -1,2 +1,65 @@ #!/bin/bash -./build/example/example + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to display usage information +show_help() { + echo "Usage: $0 [-d DEVICE_TYPE] [-b BACKEND_INSTALL_DIR]" + echo + echo "Options:" + echo " -d DEVICE_TYPE Specify the device type (default: CPU)" + echo " -b BACKEND_INSTALL_DIR Specify the backend installation directory (default: empty)" + echo " -h Show this help message" + exit 0 +} + +# Parse command line options +while getopts ":d:b:h" opt; do + case ${opt} in + d ) + DEVICE_TYPE=$OPTARG + ;; + b ) + BACKEND_INSTALL_DIR="$(realpath ${OPTARG})" + ;; + h ) + show_help + ;; + \? ) + echo "Invalid option: -$OPTARG" 1>&2 + show_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + show_help + ;; + esac +done + +# Set default values if not provided +: "${DEVICE_TYPE:=CPU}" +: "${BACKEND_INSTALL_DIR:=}" + +# Create necessary directories +mkdir -p build/example +mkdir -p build/icicle + +ICILE_DIR=$(realpath "../../../icicle_v3/") +ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" + +# Build Icicle and the example app that links to it +if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then + echo "Building icicle with CUDA backend" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle + BACKEND_INSTALL_DIR=$(realpath "build/icicle/backend") +else + echo "Building icicle without CUDA backend, BACKEND_INSTALL_DIR=${BACKEND_INSTALL_DIR}" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -S "${ICILE_DIR}" -B build/icicle +fi +cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example + +cmake --build build/icicle -j +cmake --build build/example -j + +./build/example/example "$DEVICE_TYPE" "$BACKEND_INSTALL_DIR" diff --git a/examples/c++/examples_utils.h b/examples/c++/examples_utils.h index f4e0901c..bf0be0f8 100644 --- a/examples/c++/examples_utils.h +++ b/examples/c++/examples_utils.h @@ -12,10 +12,11 @@ using FpMilliseconds = std::chrono::duration 2 && 0 != strcmp(argv[2], "")) { + const char* backend_install_dir = argv[2]; + std::cout << "Trying to load and backend device from " << backend_install_dir << std::endl; + ICICLE_CHECK(icicle_load_backend(backend_install_dir, true)); + } const char* selected_device = argc > 1 ? argv[1] : nullptr; if (selected_device) { diff --git a/examples/c++/msm/README.md b/examples/c++/msm/README.md index 76c0699d..ca6d7e8d 100644 --- a/examples/c++/msm/README.md +++ b/examples/c++/msm/README.md @@ -32,9 +32,12 @@ The configuration is passed to the kernel as a structure of type `MSMConfig`. So ## Running the example -- `cd` to your example directory -- compile with `./compile.sh` -- run with `./run.sh` +```sh +# for CPU +./run.sh -d CPU +# for CUDA +./run.sh -d CUDA -b /path/to/cuda/backend/install/dir +``` ## What's in the example diff --git a/examples/c++/msm/compile.sh b/examples/c++/msm/compile.sh deleted file mode 100755 index 75e30508..00000000 --- a/examples/c++/msm/compile.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build/example -mkdir -p build/icicle - -ICILE_DIR=$(realpath "../../../icicle_v3/") -ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" - -# Build Icicle and the example app that links to it -if [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then - echo "building icicle with CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DG2=ON -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -DBACKEND_DIR=$(realpath "build/icicle/backend") -else - echo "building icicle without CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DG2=ON -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -fi -cmake --build build/icicle -j -cmake --build build/example -j \ No newline at end of file diff --git a/examples/c++/msm/run.sh b/examples/c++/msm/run.sh index 445a49ad..34fb59a0 100755 --- a/examples/c++/msm/run.sh +++ b/examples/c++/msm/run.sh @@ -1,2 +1,65 @@ #!/bin/bash -./build/example/example $1 + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to display usage information +show_help() { + echo "Usage: $0 [-d DEVICE_TYPE] [-b BACKEND_INSTALL_DIR]" + echo + echo "Options:" + echo " -d DEVICE_TYPE Specify the device type (default: CPU)" + echo " -b BACKEND_INSTALL_DIR Specify the backend installation directory (default: empty)" + echo " -h Show this help message" + exit 0 +} + +# Parse command line options +while getopts ":d:b:h" opt; do + case ${opt} in + d ) + DEVICE_TYPE=$OPTARG + ;; + b ) + BACKEND_INSTALL_DIR="$(realpath ${OPTARG})" + ;; + h ) + show_help + ;; + \? ) + echo "Invalid option: -$OPTARG" 1>&2 + show_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + show_help + ;; + esac +done + +# Set default values if not provided +: "${DEVICE_TYPE:=CPU}" +: "${BACKEND_INSTALL_DIR:=}" + +# Create necessary directories +mkdir -p build/example +mkdir -p build/icicle + +ICILE_DIR=$(realpath "../../../icicle_v3/") +ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" + +# Build Icicle and the example app that links to it +if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then + echo "Building icicle with CUDA backend" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DG2=ON -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle + BACKEND_INSTALL_DIR=$(realpath "build/icicle/backend") +else + echo "Building icicle without CUDA backend, BACKEND_INSTALL_DIR=${BACKEND_INSTALL_DIR}" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DG2=ON -S "${ICILE_DIR}" -B build/icicle +fi +cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example + +cmake --build build/icicle -j +cmake --build build/example -j + +./build/example/example "$DEVICE_TYPE" "$BACKEND_INSTALL_DIR" diff --git a/examples/c++/ntt/README.md b/examples/c++/ntt/README.md index 5ace292f..f506eba9 100644 --- a/examples/c++/ntt/README.md +++ b/examples/c++/ntt/README.md @@ -24,9 +24,12 @@ bn254_ntt(input.get(), ntt_size, NTTDir::kForward, config, output.get()) ## Running the example -- `cd` to your example directory -- compile with `./compile.sh` -- run with `./run.sh` +```sh +# for CPU +./run.sh -d CPU +# for CUDA +./run.sh -d CUDA -b /path/to/cuda/backend/install/dir +``` ## What's in the example diff --git a/examples/c++/ntt/compile.sh b/examples/c++/ntt/compile.sh deleted file mode 100755 index e9ad97f7..00000000 --- a/examples/c++/ntt/compile.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build/example -mkdir -p build/icicle - -ICILE_DIR=$(realpath "../../../icicle_v3/") -ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" - -# Build Icicle and the example app that links to it -if [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then - echo "building icicle with CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -DBACKEND_DIR=$(realpath "build/icicle/backend") -else - echo "building icicle without CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -fi -cmake --build build/icicle -j -cmake --build build/example -j \ No newline at end of file diff --git a/examples/c++/ntt/run.sh b/examples/c++/ntt/run.sh index a7cac652..23615cba 100755 --- a/examples/c++/ntt/run.sh +++ b/examples/c++/ntt/run.sh @@ -1,2 +1,65 @@ #!/bin/bash -./build/example/example $1 \ No newline at end of file + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to display usage information +show_help() { + echo "Usage: $0 [-d DEVICE_TYPE] [-b BACKEND_INSTALL_DIR]" + echo + echo "Options:" + echo " -d DEVICE_TYPE Specify the device type (default: CPU)" + echo " -b BACKEND_INSTALL_DIR Specify the backend installation directory (default: empty)" + echo " -h Show this help message" + exit 0 +} + +# Parse command line options +while getopts ":d:b:h" opt; do + case ${opt} in + d ) + DEVICE_TYPE=$OPTARG + ;; + b ) + BACKEND_INSTALL_DIR="$(realpath ${OPTARG})" + ;; + h ) + show_help + ;; + \? ) + echo "Invalid option: -$OPTARG" 1>&2 + show_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + show_help + ;; + esac +done + +# Set default values if not provided +: "${DEVICE_TYPE:=CPU}" +: "${BACKEND_INSTALL_DIR:=}" + +# Create necessary directories +mkdir -p build/example +mkdir -p build/icicle + +ICILE_DIR=$(realpath "../../../icicle_v3/") +ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" + +# Build Icicle and the example app that links to it +if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then + echo "Building icicle with CUDA backend" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle + BACKEND_INSTALL_DIR=$(realpath "build/icicle/backend") +else + echo "Building icicle without CUDA backend, BACKEND_INSTALL_DIR=${BACKEND_INSTALL_DIR}" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -S "${ICILE_DIR}" -B build/icicle +fi +cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example + +cmake --build build/icicle -j +cmake --build build/example -j + +./build/example/example "$DEVICE_TYPE" "$BACKEND_INSTALL_DIR" diff --git a/examples/c++/pedersen-commitment/README.md b/examples/c++/pedersen-commitment/README.md index 8dabcafe..97dffa20 100644 --- a/examples/c++/pedersen-commitment/README.md +++ b/examples/c++/pedersen-commitment/README.md @@ -10,10 +10,12 @@ An example of MSM is [here](../msm/README.md). ## Running the example -- `cd` to your example directory -- compile with `./compile.sh` -- run with `./run.sh` - +```sh +# for CPU +./run.sh -d CPU +# for CUDA +./run.sh -d CUDA -b /path/to/cuda/backend/install/dir +``` ## Concise Explanation We recommend this simple [explanation](https://www.rareskills.io/post/pedersen-commitment). diff --git a/examples/c++/pedersen-commitment/compile.sh b/examples/c++/pedersen-commitment/compile.sh deleted file mode 100755 index da07bafc..00000000 --- a/examples/c++/pedersen-commitment/compile.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build/example -mkdir -p build/icicle - -ICILE_DIR=$(realpath "../../../icicle_v3/") -ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" - -# Build Icicle and the example app that links to it -if [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then - echo "building icicle with CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -DBACKEND_DIR=$(realpath "build/icicle/backend") -else - echo "building icicle without CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -fi -cmake --build build/icicle -j -cmake --build build/example -j \ No newline at end of file diff --git a/examples/c++/pedersen-commitment/run.sh b/examples/c++/pedersen-commitment/run.sh index a7cac652..ada4862a 100755 --- a/examples/c++/pedersen-commitment/run.sh +++ b/examples/c++/pedersen-commitment/run.sh @@ -1,2 +1,65 @@ #!/bin/bash -./build/example/example $1 \ No newline at end of file + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to display usage information +show_help() { + echo "Usage: $0 [-d DEVICE_TYPE] [-b BACKEND_INSTALL_DIR]" + echo + echo "Options:" + echo " -d DEVICE_TYPE Specify the device type (default: CPU)" + echo " -b BACKEND_INSTALL_DIR Specify the backend installation directory (default: empty)" + echo " -h Show this help message" + exit 0 +} + +# Parse command line options +while getopts ":d:b:h" opt; do + case ${opt} in + d ) + DEVICE_TYPE=$OPTARG + ;; + b ) + BACKEND_INSTALL_DIR="$(realpath ${OPTARG})" + ;; + h ) + show_help + ;; + \? ) + echo "Invalid option: -$OPTARG" 1>&2 + show_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + show_help + ;; + esac +done + +# Set default values if not provided +: "${DEVICE_TYPE:=CPU}" +: "${BACKEND_INSTALL_DIR:=}" + +# Create necessary directories +mkdir -p build/example +mkdir -p build/icicle + +ICILE_DIR=$(realpath "../../../icicle_v3/") +ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" + +# Build Icicle and the example app that links to it +if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then + echo "Building icicle with CUDA backend" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle + BACKEND_INSTALL_DIR=$(realpath "build/icicle/backend") +else + echo "Building icicle without CUDA backend, BACKEND_INSTALL_DIR=${BACKEND_INSTALL_DIR}" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -S "${ICILE_DIR}" -B build/icicle +fi +cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example + +cmake --build build/icicle -j +cmake --build build/example -j + +./build/example/example "$DEVICE_TYPE" "$BACKEND_INSTALL_DIR" diff --git a/examples/c++/polynomial-api/README.md b/examples/c++/polynomial-api/README.md index 8aab545e..d1b214f6 100644 --- a/examples/c++/polynomial-api/README.md +++ b/examples/c++/polynomial-api/README.md @@ -9,9 +9,10 @@ Polynomials are crucial for Zero-Knowledge Proofs (ZKPs): they enable efficient To run example, from project root directory: ```sh -cd examples/c++/polynomial-api -./compile.sh -./run.sh +# for CPU +./run.sh -d CPU +# for CUDA +./run.sh -d CUDA -b /path/to/cuda/backend/install/dir ``` To change the scalar field, modify `compile.h` to build the corresponding lib and `CMakeLists.txt` to link to that lib and set `FIELD_ID` correspondingly. diff --git a/examples/c++/polynomial-api/compile.sh b/examples/c++/polynomial-api/compile.sh deleted file mode 100755 index da07bafc..00000000 --- a/examples/c++/polynomial-api/compile.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build/example -mkdir -p build/icicle - -ICILE_DIR=$(realpath "../../../icicle_v3/") -ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" - -# Build Icicle and the example app that links to it -if [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then - echo "building icicle with CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -DBACKEND_DIR=$(realpath "build/icicle/backend") -else - echo "building icicle without CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -fi -cmake --build build/icicle -j -cmake --build build/example -j \ No newline at end of file diff --git a/examples/c++/polynomial-api/example.cpp b/examples/c++/polynomial-api/example.cpp index 76189a4f..79aa3caa 100644 --- a/examples/c++/polynomial-api/example.cpp +++ b/examples/c++/polynomial-api/example.cpp @@ -21,27 +21,28 @@ const auto four = scalar_t::from(4); const auto five = scalar_t::from(5); const auto minus_one = zero - one; -static std::unique_ptr generate_pows(scalar_t tau, uint32_t size){ - auto vec = std::make_unique(size); - vec[0] = scalar_t::one(); - for (size_t i = 1; i < size; ++i) { - vec[i] = vec[i-1] * tau; +static std::unique_ptr generate_pows(scalar_t tau, uint32_t size) +{ + auto vec = std::make_unique(size); + vec[0] = scalar_t::one(); + for (size_t i = 1; i < size; ++i) { + vec[i] = vec[i - 1] * tau; } return std::move(vec); } -static std::unique_ptr generate_SRS(uint32_t size) { +static std::unique_ptr generate_SRS(uint32_t size) +{ auto secret_scalar = scalar_t::rand_host(); auto gen = projective_t::generator(); - auto pows_of_tau = generate_pows(secret_scalar,size); + auto pows_of_tau = generate_pows(secret_scalar, size); auto SRS = std::make_unique(size); for (size_t i = 0; i < size; ++i) { - SRS[i] = projective_t::to_affine(pows_of_tau[i] * gen); + SRS[i] = projective_t::to_affine(pows_of_tau[i] * gen); } return std::move(SRS); } - void example_evaluate() { std::cout << std::endl << "Example: Polynomial evaluation on random value" << std::endl; @@ -319,110 +320,108 @@ void example_device_memory_view() ntt(d_coeffs.get(), size, NTTDir::kForward, ntt_config, coset_evals.get()); } - void example_commit_with_device_memory_view() { - //declare time vars + // declare time vars std::chrono::time_point start, end; std::chrono::milliseconds duration; - std::cout << std::endl << "Example: a) commit with Polynomial views [(f1+f2)^2 + (f1-f2)^2 ]_1 = [4 (f1^2+ f_2^2)]_1" << std::endl; - std::cout<< "Example: b) commit with Polynomial views [(f1+f2)^2 - (f1-f2)^2 ]_1 = [4 f1 *f_2]_1" << std::endl; + std::cout << std::endl + << "Example: a) commit with Polynomial views [(f1+f2)^2 + (f1-f2)^2 ]_1 = [4 (f1^2+ f_2^2)]_1" << std::endl; + std::cout << "Example: b) commit with Polynomial views [(f1+f2)^2 - (f1-f2)^2 ]_1 = [4 f1 *f_2]_1" << std::endl; int N = 1025; - //generate group elements string of length N: (1, beta,beta^2....,beta^{N-1}). g + // generate group elements string of length N: (1, beta,beta^2....,beta^{N-1}). g std::cout << "Setup: Generating mock SRS" << std::endl; start = std::chrono::high_resolution_clock::now(); - auto SRS = generate_SRS(2*N); - //Allocate memory on device (points) + auto SRS = generate_SRS(2 * N); + // Allocate memory on device (points) affine_t* points_d; - ICICLE_CHECK(icicle_malloc((void**)&points_d, sizeof(affine_t)* 2 * N)); + ICICLE_CHECK(icicle_malloc((void**)&points_d, sizeof(affine_t) * 2 * N)); // copy SRS to device (could have generated on device, but gives an indicator) - ICICLE_CHECK(icicle_copy(points_d, SRS.get(), sizeof(affine_t)* 2 * N)); + ICICLE_CHECK(icicle_copy(points_d, SRS.get(), sizeof(affine_t) * 2 * N)); end = std::chrono::high_resolution_clock::now(); duration = std::chrono::duration_cast(end - start); - std::cout << "Setup: SRS of length "<< N << " generated and loaded to device. Took: " << duration.count() << " milliseconds" << std::endl; - - //goal: - //test commitment equality [(f1+f2)^2 + (f1-f2)^2 ]_1 = [4 (f1^2+ f_2^2)]_1 - //test commitment equality [(f1+f2)^2 - (f1-f2)^2 ]_1 = [4 f1 *f_2]_1 - //note: using polyapi to gen scalars: already on device. - std::cout << "Setup: Generating polys (on device) f1,f2 of log degree " << log2(N-1) << std::endl; + std::cout << "Setup: SRS of length " << N << " generated and loaded to device. Took: " << duration.count() + << " milliseconds" << std::endl; + + // goal: + // test commitment equality [(f1+f2)^2 + (f1-f2)^2 ]_1 = [4 (f1^2+ f_2^2)]_1 + // test commitment equality [(f1+f2)^2 - (f1-f2)^2 ]_1 = [4 f1 *f_2]_1 + // note: using polyapi to gen scalars: already on device. + std::cout << "Setup: Generating polys (on device) f1,f2 of log degree " << log2(N - 1) << std::endl; start = std::chrono::high_resolution_clock::now(); auto f1 = randomize_polynomial(N); auto f2 = randomize_polynomial(N); end = std::chrono::high_resolution_clock::now(); duration = std::chrono::duration_cast(end - start); std::cout << "Setup: Gen poly done. Took: " << duration.count() << " milliseconds" << std::endl; - - //deg 2N constraints (f1+f2)^2 + (f1-f2)^2 = 2 (f1^2+ f_2^2) - std::cout << "Computing constraints..start "<< std::endl; + + // deg 2N constraints (f1+f2)^2 + (f1-f2)^2 = 2 (f1^2+ f_2^2) + std::cout << "Computing constraints..start " << std::endl; start = std::chrono::high_resolution_clock::now(); - auto L1 = (f1+f2)*(f1+f2) + (f1-f2)*(f1-f2); - auto R1 = scalar_t::from(2) * (f1*f1 + f2*f2); - //deg 2N constraints (f1+f2)^2 - (f1-f2)^2 = 4 f1 *f_2 - auto L2 = (f1+f2)*(f1+f2) - (f1-f2)*(f1-f2); + auto L1 = (f1 + f2) * (f1 + f2) + (f1 - f2) * (f1 - f2); + auto R1 = scalar_t::from(2) * (f1 * f1 + f2 * f2); + // deg 2N constraints (f1+f2)^2 - (f1-f2)^2 = 4 f1 *f_2 + auto L2 = (f1 + f2) * (f1 + f2) - (f1 - f2) * (f1 - f2); auto R2 = scalar_t::from(4) * f1 * f2; end = std::chrono::high_resolution_clock::now(); duration = std::chrono::duration_cast(end - start); - std::cout << "Computing constraints..done. Took: " << duration.count() << " milliseconds"<< std::endl; - + std::cout << "Computing constraints..done. Took: " << duration.count() << " milliseconds" << std::endl; + // extract coeff using coeff view auto [viewL1, sizeL1] = L1.get_coefficients_view(); - auto [viewL2, sizeL2] = L2.get_coefficients_view(); + auto [viewL2, sizeL2] = L2.get_coefficients_view(); auto [viewR1, sizeR1] = R1.get_coefficients_view(); auto [viewR2, sizeR2] = R2.get_coefficients_view(); - - std::cout << "Computing Commitments with poly view"<< std::endl; + + std::cout << "Computing Commitments with poly view" << std::endl; start = std::chrono::high_resolution_clock::now(); MSMConfig config = default_msm_config(); config.are_points_on_device = true; config.are_scalars_on_device = true; - - //host vars (for result) + + // host vars (for result) projective_t hL1{}, hL2{}, hR1{}, hR2{}; - //straightforward msm bn254 api: no batching - msm(viewL1.get(),points_d,N,config,&hL1); - msm(viewL2.get(),points_d,N,config,&hL2); - msm(viewR1.get(),points_d,N,config,&hR1); - msm(viewR2.get(),points_d,N,config,&hR2); + // straightforward msm bn254 api: no batching + msm(viewL1.get(), points_d, N, config, &hL1); + msm(viewL2.get(), points_d, N, config, &hL2); + msm(viewR1.get(), points_d, N, config, &hR1); + msm(viewR2.get(), points_d, N, config, &hR2); end = std::chrono::high_resolution_clock::now(); duration = std::chrono::duration_cast(end - start); - std::cout << "Commitments done. Took: " << duration.count() << " milliseconds"<< std::endl; - - //sanity checks + std::cout << "Commitments done. Took: " << duration.count() << " milliseconds" << std::endl; + + // sanity checks auto affL1 = projective_t::to_affine(hL1); auto affR1 = projective_t::to_affine(hR1); auto affL2 = projective_t::to_affine(hL2); auto affR2 = projective_t::to_affine(hR2); - //test commitment equality [(f1+f2)^2 + (f1-f2)^2]_1 = [4 (f_1^2+f_2^2]_1 - assert(affL1.x==affR1.x && affL1.y==affR1.y); - std::cout << "commitment [(f1+f2)^2 + (f1-f2)^2]_1:" << std::endl; + // test commitment equality [(f1+f2)^2 + (f1-f2)^2]_1 = [4 (f_1^2+f_2^2]_1 + assert(affL1.x == affR1.x && affL1.y == affR1.y); + std::cout << "commitment [(f1+f2)^2 + (f1-f2)^2]_1:" << std::endl; std::cout << "[x: " << affL1.x << ", y: " << affL1.y << "]" << std::endl; - std::cout << "commitment [[2 (f_1^2+f_2^2]_1:" <&2 + show_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + show_help + ;; + esac +done + +# Set default values if not provided +: "${DEVICE_TYPE:=CPU}" +: "${BACKEND_INSTALL_DIR:=}" + +# Create necessary directories +mkdir -p build/example +mkdir -p build/icicle + +ICILE_DIR=$(realpath "../../../icicle_v3/") +ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" + +# Build Icicle and the example app that links to it +if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then + echo "Building icicle with CUDA backend" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle + BACKEND_INSTALL_DIR=$(realpath "build/icicle/backend") +else + echo "Building icicle without CUDA backend, BACKEND_INSTALL_DIR=${BACKEND_INSTALL_DIR}" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -S "${ICILE_DIR}" -B build/icicle +fi +cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example + +cmake --build build/icicle -j +cmake --build build/example -j + +./build/example/example "$DEVICE_TYPE" "$BACKEND_INSTALL_DIR" diff --git a/examples/c++/polynomial_multiplication/README.md b/examples/c++/polynomial_multiplication/README.md index 7248f20f..9bf14499 100644 --- a/examples/c++/polynomial_multiplication/README.md +++ b/examples/c++/polynomial_multiplication/README.md @@ -14,9 +14,12 @@ Icicle provides polynomial multiplication using the Number Theoretical Transform ## Running the example -- `cd` to your example directory -- compile with `./compile.sh` -- run with `./run.sh` +```sh +# for CPU +./run.sh -d CPU +# for CUDA +./run.sh -d CUDA -b /path/to/cuda/backend/install/dir +``` ## What's in the example diff --git a/examples/c++/polynomial_multiplication/compile.sh b/examples/c++/polynomial_multiplication/compile.sh deleted file mode 100755 index da07bafc..00000000 --- a/examples/c++/polynomial_multiplication/compile.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build/example -mkdir -p build/icicle - -ICILE_DIR=$(realpath "../../../icicle_v3/") -ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" - -# Build Icicle and the example app that links to it -if [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then - echo "building icicle with CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -DBACKEND_DIR=$(realpath "build/icicle/backend") -else - echo "building icicle without CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -fi -cmake --build build/icicle -j -cmake --build build/example -j \ No newline at end of file diff --git a/examples/c++/polynomial_multiplication/example.cpp b/examples/c++/polynomial_multiplication/example.cpp index 7b6fa43a..b8a61d17 100644 --- a/examples/c++/polynomial_multiplication/example.cpp +++ b/examples/c++/polynomial_multiplication/example.cpp @@ -30,23 +30,12 @@ void incremental_values(scalar_t* res, uint32_t count) int main(int argc, char** argv) { - try_load_and_set_backend_device(argc - 1, argv + 1); + try_load_and_set_backend_device(argc, argv); - int NTT_LOG_SIZE = 18; + int NTT_LOG_SIZE = 20; int NTT_SIZE = 1 << NTT_LOG_SIZE; // init domain - auto ntt_config = default_ntt_config(); - ConfigExtension ntt_cfg_ext; - ntt_config.ext = &ntt_cfg_ext; - if (argc > 1) { - int ntt_algorithm = atoi(argv[1]); - ICICLE_ASSERT(ntt_algorithm >= 1 && ntt_algorithm <= 2) << "Invalid ntt-algorithm index"; - ntt_cfg_ext.set("ntt_algorithm", ntt_algorithm); - const char* ntt_algorithm_str = ntt_algorithm == 1 ? "Radix-2" : "Mixed-Radix"; - std::cout << "Polynomial multiplication with " << ntt_algorithm_str << " NTT: "; - } - scalar_t basic_root = scalar_t::omega(NTT_LOG_SIZE); bn254_ntt_init_domain(&basic_root, default_ntt_init_domain_config()); @@ -71,6 +60,7 @@ int main(int argc, char** argv) START_TIMER(poly_multiply) // (3) NTT for A,B from host memory to device-memory + auto ntt_config = default_ntt_config(); ntt_config.are_inputs_on_device = false; ntt_config.are_outputs_on_device = true; ntt_config.ordering = Ordering::kNM; @@ -94,7 +84,7 @@ int main(int argc, char** argv) ntt_config.ordering = Ordering::kMN; ICICLE_CHECK(bn254_ntt(d_polyRes, NTT_SIZE, NTTDir::kInverse, ntt_config, d_polyRes)); - if (print) { END_TIMER(poly_multiply, ""); } + if (print) { END_TIMER(poly_multiply, "polynomial multiplication took"); } ICICLE_CHECK(icicle_free(d_polyA)); ICICLE_CHECK(icicle_free(d_polyB)); diff --git a/examples/c++/polynomial_multiplication/run.sh b/examples/c++/polynomial_multiplication/run.sh index 1523e305..23615cba 100755 --- a/examples/c++/polynomial_multiplication/run.sh +++ b/examples/c++/polynomial_multiplication/run.sh @@ -1,3 +1,65 @@ #!/bin/bash -./build/example/example 1 $1 # radix2 -./build/example/example 2 $1 # mixed-radix + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to display usage information +show_help() { + echo "Usage: $0 [-d DEVICE_TYPE] [-b BACKEND_INSTALL_DIR]" + echo + echo "Options:" + echo " -d DEVICE_TYPE Specify the device type (default: CPU)" + echo " -b BACKEND_INSTALL_DIR Specify the backend installation directory (default: empty)" + echo " -h Show this help message" + exit 0 +} + +# Parse command line options +while getopts ":d:b:h" opt; do + case ${opt} in + d ) + DEVICE_TYPE=$OPTARG + ;; + b ) + BACKEND_INSTALL_DIR="$(realpath ${OPTARG})" + ;; + h ) + show_help + ;; + \? ) + echo "Invalid option: -$OPTARG" 1>&2 + show_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + show_help + ;; + esac +done + +# Set default values if not provided +: "${DEVICE_TYPE:=CPU}" +: "${BACKEND_INSTALL_DIR:=}" + +# Create necessary directories +mkdir -p build/example +mkdir -p build/icicle + +ICILE_DIR=$(realpath "../../../icicle_v3/") +ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" + +# Build Icicle and the example app that links to it +if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then + echo "Building icicle with CUDA backend" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle + BACKEND_INSTALL_DIR=$(realpath "build/icicle/backend") +else + echo "Building icicle without CUDA backend, BACKEND_INSTALL_DIR=${BACKEND_INSTALL_DIR}" + cmake -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DMSM=OFF -S "${ICILE_DIR}" -B build/icicle +fi +cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example + +cmake --build build/icicle -j +cmake --build build/example -j + +./build/example/example "$DEVICE_TYPE" "$BACKEND_INSTALL_DIR" diff --git a/examples/c++/risc0/README.md b/examples/c++/risc0/README.md index 743d003d..fc10fdcb 100644 --- a/examples/c++/risc0/README.md +++ b/examples/c++/risc0/README.md @@ -21,9 +21,10 @@ The key enabler for *recursion* is the *redundancy* of polynomial commitments, h To run example, from project root directory: ```sh -cd examples/c++/risc0 -./compile.sh -./run.sh +# for CPU +./run.sh -d CPU +# for CUDA +./run.sh -d CUDA -b /path/to/cuda/backend/install/dir ``` ## What's in the example diff --git a/examples/c++/risc0/compile.sh b/examples/c++/risc0/compile.sh deleted file mode 100755 index 0732dc7b..00000000 --- a/examples/c++/risc0/compile.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -mkdir -p build/example -mkdir -p build/icicle - -ICILE_DIR=$(realpath "../../../icicle_v3/") -ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" - -# Build Icicle and the example app that links to it -if [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then - echo "building icicle with CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DFIELD=babybear -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -DBACKEND_DIR=$(realpath "build/icicle/backend") -else - echo "building icicle without CUDA backend" - cmake -DCMAKE_BUILD_TYPE=Release -DFIELD=babybear -S "${ICILE_DIR}" -B build/icicle - cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example -fi -cmake --build build/icicle -j -cmake --build build/example -j \ No newline at end of file diff --git a/examples/c++/risc0/run.sh b/examples/c++/risc0/run.sh index 445a49ad..5083180e 100755 --- a/examples/c++/risc0/run.sh +++ b/examples/c++/risc0/run.sh @@ -1,2 +1,65 @@ #!/bin/bash -./build/example/example $1 + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to display usage information +show_help() { + echo "Usage: $0 [-d DEVICE_TYPE] [-b BACKEND_INSTALL_DIR]" + echo + echo "Options:" + echo " -d DEVICE_TYPE Specify the device type (default: CPU)" + echo " -b BACKEND_INSTALL_DIR Specify the backend installation directory (default: empty)" + echo " -h Show this help message" + exit 0 +} + +# Parse command line options +while getopts ":d:b:h" opt; do + case ${opt} in + d ) + DEVICE_TYPE=$OPTARG + ;; + b ) + BACKEND_INSTALL_DIR="$(realpath ${OPTARG})" + ;; + h ) + show_help + ;; + \? ) + echo "Invalid option: -$OPTARG" 1>&2 + show_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + show_help + ;; + esac +done + +# Set default values if not provided +: "${DEVICE_TYPE:=CPU}" +: "${BACKEND_INSTALL_DIR:=}" + +# Create necessary directories +mkdir -p build/example +mkdir -p build/icicle + +ICILE_DIR=$(realpath "../../../icicle_v3/") +ICICLE_CUDA_BACKEND_DIR="${ICILE_DIR}/backend/cuda" + +# Build Icicle and the example app that links to it +if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_BACKEND_DIR}" ]; then + echo "Building icicle with CUDA backend" + cmake -DCMAKE_BUILD_TYPE=Release -DFIELD=babybear -DCUDA_BACKEND=local -S "${ICILE_DIR}" -B build/icicle + BACKEND_INSTALL_DIR=$(realpath "build/icicle/backend") +else + echo "Building icicle without CUDA backend, BACKEND_INSTALL_DIR=${BACKEND_INSTALL_DIR}" + cmake -DCMAKE_BUILD_TYPE=Release -DFIELD=babybear -S "${ICILE_DIR}" -B build/icicle +fi +cmake -DCMAKE_BUILD_TYPE=Release -S . -B build/example + +cmake --build build/icicle -j +cmake --build build/example -j + +./build/example/example "$DEVICE_TYPE" "$BACKEND_INSTALL_DIR"