mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-10 07:08:03 -05:00
feat(gpu): add fast op-sequence tests in makefile and the CI
This commit is contained in:
118
.github/workflows/gpu_integer_short_op_sequence_tests.yml
vendored
Normal file
118
.github/workflows/gpu_integer_short_op_sequence_tests.yml
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
name: Cuda - Short Op-sequence Tests on GPU
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
ACTION_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
RUSTFLAGS: "-C target-cpu=native"
|
||||
RUST_BACKTRACE: "full"
|
||||
RUST_MIN_STACK: "8388608"
|
||||
SLACK_CHANNEL: ${{ secrets.SLACK_CHANNEL }}
|
||||
SLACK_ICON: https://pbs.twimg.com/profile_images/1274014582265298945/OjBKP9kn_400x400.png
|
||||
SLACK_USERNAME: ${{ secrets.BOT_USERNAME }}
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
|
||||
CHECKOUT_TOKEN: ${{ secrets.REPO_CHECKOUT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
||||
on:
|
||||
# Allows you to run this workflow manually from the Actions tab as an alternative.
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Nightly tests will be triggered each evening 8p.m.
|
||||
- cron: "0 20 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
setup-instance:
|
||||
name: Setup instance (gpu-tests)
|
||||
if: github.event_name != 'schedule' ||
|
||||
(github.event_name == 'schedule' && github.repository == 'zama-ai/tfhe-rs')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner-name: ${{ steps.start-instance.outputs.label }}
|
||||
steps:
|
||||
- name: Start instance
|
||||
id: start-instance
|
||||
uses: zama-ai/slab-github-runner@79939325c3c429837c10d6041e4fd8589d328bac
|
||||
with:
|
||||
mode: start
|
||||
github-token: ${{ secrets.SLAB_ACTION_TOKEN }}
|
||||
slab-url: ${{ secrets.SLAB_BASE_URL }}
|
||||
job-secret: ${{ secrets.JOB_SECRET }}
|
||||
backend: hyperstack
|
||||
profile: multi-gpu-test
|
||||
|
||||
cuda-tests:
|
||||
name: Short op-sequence GPU tests
|
||||
needs: [ setup-instance ]
|
||||
concurrency:
|
||||
group: ${{ github.workflow_ref }}_${{github.event_name}}
|
||||
cancel-in-progress: true
|
||||
runs-on: ${{ needs.setup-instance.outputs.runner-name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# explicit include-based build matrix, of known valid options
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
cuda: "12.2"
|
||||
gcc: 11
|
||||
timeout-minutes: 4320 # 72 hours
|
||||
steps:
|
||||
- name: Checkout tfhe-rs
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
persist-credentials: 'false'
|
||||
token: ${{ env.CHECKOUT_TOKEN }}
|
||||
|
||||
- name: Setup Hyperstack dependencies
|
||||
uses: ./.github/actions/gpu_setup
|
||||
with:
|
||||
cuda-version: ${{ matrix.cuda }}
|
||||
gcc-version: ${{ matrix.gcc }}
|
||||
|
||||
- name: Install latest stable
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # zizmor: ignore[stale-action-refs] this action doesn't create releases
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
make test_integer_short_op_sequence_gpu
|
||||
|
||||
slack-notify:
|
||||
name: Slack Notification
|
||||
needs: [ setup-instance, cuda-tests ]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ always() && needs.cuda-tests.result != 'skipped' && failure() }}
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Send message
|
||||
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661
|
||||
env:
|
||||
SLACK_COLOR: ${{ needs.cuda-tests.result }}
|
||||
SLACK_MESSAGE: "Integer GPU fast op-sequence tests finished with status: ${{ needs.cuda-tests.result }}. (${{ env.ACTION_RUN_URL }})"
|
||||
|
||||
teardown-instance:
|
||||
name: Teardown instance (gpu-tests)
|
||||
if: ${{ always() && needs.setup-instance.result == 'success' }}
|
||||
needs: [ setup-instance, cuda-tests ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Stop instance
|
||||
id: stop-instance
|
||||
uses: zama-ai/slab-github-runner@79939325c3c429837c10d6041e4fd8589d328bac
|
||||
with:
|
||||
mode: stop
|
||||
github-token: ${{ secrets.SLAB_ACTION_TOKEN }}
|
||||
slab-url: ${{ secrets.SLAB_BASE_URL }}
|
||||
job-secret: ${{ secrets.JOB_SECRET }}
|
||||
label: ${{ needs.setup-instance.outputs.runner-name }}
|
||||
|
||||
- name: Slack Notification
|
||||
if: ${{ failure() }}
|
||||
continue-on-error: true
|
||||
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Instance teardown (gpu-short-op-sequence-tests) finished with status: ${{ job.status }}. (${{ env.ACTION_RUN_URL }})"
|
||||
9
Makefile
9
Makefile
@@ -666,6 +666,15 @@ test_integer_long_run_gpu: install_rs_check_toolchain install_cargo_nextest
|
||||
--cargo-profile "$(CARGO_PROFILE)" --avx512-support "$(AVX512_SUPPORT)" \
|
||||
--tfhe-package "$(TFHE_SPEC)" --backend "gpu"
|
||||
|
||||
.PHONY: test_integer_short_op_sequence_gpu # Run the long run integer tests on the gpu backend
|
||||
test_integer_short_op_sequence_gpu: install_rs_check_toolchain install_cargo_nextest
|
||||
BIG_TESTS_INSTANCE="$(BIG_TESTS_INSTANCE)" \
|
||||
SHORT_TESTS=TRUE \
|
||||
./scripts/integer-tests.sh --rust-toolchain $(CARGO_RS_BUILD_TOOLCHAIN) \
|
||||
--cargo-profile "$(CARGO_PROFILE)" --avx512-support "$(AVX512_SUPPORT)" \
|
||||
--tfhe-package "$(TFHE_SPEC)" --backend "gpu"
|
||||
|
||||
|
||||
.PHONY: test_integer_compression
|
||||
test_integer_compression: install_rs_build_toolchain
|
||||
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) test --profile $(CARGO_PROFILE) \
|
||||
|
||||
@@ -24,7 +24,7 @@ RUST_TOOLCHAIN="+stable"
|
||||
multi_bit_argument=
|
||||
sign_argument=
|
||||
fast_tests_argument=
|
||||
long_tests_argument=
|
||||
op_sequence_tests_argument=
|
||||
nightly_tests_argument=
|
||||
no_big_params_argument=
|
||||
cargo_profile="release"
|
||||
@@ -96,7 +96,11 @@ if [[ "${FAST_TESTS}" == TRUE ]]; then
|
||||
fi
|
||||
|
||||
if [[ "${LONG_TESTS}" == TRUE ]]; then
|
||||
long_tests_argument=--long-tests
|
||||
op_sequence_tests_argument=--long-tests
|
||||
fi
|
||||
|
||||
if [[ "${SHORT_TESTS}" == TRUE ]]; then
|
||||
op_sequence_tests_argument=--short-tests
|
||||
fi
|
||||
|
||||
if [[ "${NIGHTLY_TESTS}" == TRUE ]]; then
|
||||
@@ -145,7 +149,7 @@ if [[ "${backend}" == "gpu" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
filter_expression=$(/usr/bin/python3 scripts/test_filtering.py --layer integer --backend "${backend}" ${fast_tests_argument} ${long_tests_argument} ${nightly_tests_argument} ${multi_bit_argument} ${sign_argument} ${no_big_params_argument})
|
||||
filter_expression=$(/usr/bin/python3 scripts/test_filtering.py --layer integer --backend "${backend}" ${fast_tests_argument} ${op_sequence_tests_argument} ${nightly_tests_argument} ${multi_bit_argument} ${sign_argument} ${no_big_params_argument})
|
||||
|
||||
if [[ "${FAST_TESTS}" == "TRUE" ]]; then
|
||||
echo "Running 'fast' test set"
|
||||
@@ -157,6 +161,10 @@ if [[ "${LONG_TESTS}" == "TRUE" ]]; then
|
||||
echo "Running 'long run' test set"
|
||||
fi
|
||||
|
||||
if [[ "${SHORT_TESTS}" == "TRUE" ]]; then
|
||||
echo "Running 'short op-sequence' test set"
|
||||
fi
|
||||
|
||||
if [[ "${NIGHTLY_TESTS}" == "TRUE" ]]; then
|
||||
echo "Running 'nightly' test set"
|
||||
fi
|
||||
@@ -172,7 +180,7 @@ cargo "${RUST_TOOLCHAIN}" nextest run \
|
||||
--test-threads "${test_threads}" \
|
||||
-E "$filter_expression"
|
||||
|
||||
if [[ -z ${multi_bit_argument} && -z ${long_tests_argument} ]]; then
|
||||
if [[ -z ${multi_bit_argument} && -z ${op_sequence_tests_argument} ]]; then
|
||||
cargo "${RUST_TOOLCHAIN}" test \
|
||||
--profile "${cargo_profile}" \
|
||||
--package "${tfhe_package}" \
|
||||
|
||||
@@ -32,6 +32,12 @@ parser.add_argument(
|
||||
action="store_true",
|
||||
help="Run only the long tests suite",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--short-tests",
|
||||
dest="short_tests",
|
||||
action="store_true",
|
||||
help="Run only the short tests suite",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--nightly-tests",
|
||||
dest="nightly_tests",
|
||||
@@ -107,7 +113,10 @@ def filter_integer_tests(input_args):
|
||||
("_multi_bit", "_group_[0-9]") if input_args.multi_bit else ("", "")
|
||||
)
|
||||
backend_filter = ""
|
||||
if not input_args.long_tests:
|
||||
# Regular tests are mostly unit-tests
|
||||
regular_test_suite = not input_args.long_tests and not input_args.short_tests
|
||||
filter_expression = []
|
||||
if regular_test_suite:
|
||||
if input_args.backend == "gpu":
|
||||
backend_filter = "gpu::"
|
||||
if multi_bit_filter:
|
||||
@@ -153,7 +162,10 @@ def filter_integer_tests(input_args):
|
||||
for pattern in excluded_tests:
|
||||
filter_expression.append(f"not test({pattern})")
|
||||
|
||||
else:
|
||||
# Long and short op-sequence tests are more complex
|
||||
# tests that run random operations in sequence
|
||||
elif input_args.long_tests :
|
||||
# Long tests run many operations (e.g. 20 000)
|
||||
if input_args.backend == "gpu":
|
||||
filter_expression = [
|
||||
"test(/^integer::gpu::server_key::radix::tests_long_run.*/)"
|
||||
@@ -162,6 +174,19 @@ def filter_integer_tests(input_args):
|
||||
filter_expression = [
|
||||
"test(/^integer::server_key::radix_parallel::tests_long_run.*/)"
|
||||
]
|
||||
elif input_args.short_tests:
|
||||
# Short op-sequence tests run few iterations (tens or hundreds)
|
||||
if input_args.backend == "gpu":
|
||||
filter_expression = [
|
||||
"test(/^integer::gpu::server_key::radix::tests_short_run.*/)"
|
||||
]
|
||||
elif input_args.backend == "cpu":
|
||||
filter_expression = [
|
||||
"test(/^integer::server_key::radix_parallel::tests_short_run/)"
|
||||
]
|
||||
assert False, "Short tests not yet implemented for cpu backend"
|
||||
else:
|
||||
assert False, "Invalid test suite selection"
|
||||
|
||||
return " and ".join(filter_expression)
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ mod tests_signed;
|
||||
#[cfg(test)]
|
||||
mod tests_unsigned;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests_short_run;
|
||||
|
||||
impl CudaServerKey {
|
||||
/// Create a trivial ciphertext filled with zeros on the GPU.
|
||||
///
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::integer::server_key::radix_parallel::tests_long_run::test_signed_rand
|
||||
SignedScalarOverflowingOpExecutor, SignedScalarShiftRotateExecutor, SignedSelectOpExecutor,
|
||||
SignedShiftRotateExecutor, SignedUnaryOpExecutor,
|
||||
};
|
||||
use crate::integer::server_key::radix_parallel::tests_long_run::NB_TESTS_LONG_RUN;
|
||||
use crate::shortint::parameters::*;
|
||||
use std::cmp::{max, min};
|
||||
|
||||
@@ -15,6 +16,13 @@ create_gpu_parameterized_test!(signed_random_op_sequence {
|
||||
PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128
|
||||
});
|
||||
fn signed_random_op_sequence<P>(param: P)
|
||||
where
|
||||
P: Into<TestParameters> + Clone,
|
||||
{
|
||||
signed_random_op_sequence_generic(param, NB_TESTS_LONG_RUN);
|
||||
}
|
||||
|
||||
pub(crate) fn signed_random_op_sequence_generic<P>(param: P, num_iterations: usize)
|
||||
where
|
||||
P: Into<TestParameters> + Clone,
|
||||
{
|
||||
@@ -416,6 +424,7 @@ where
|
||||
|
||||
signed_random_op_sequence_test(
|
||||
param,
|
||||
num_iterations,
|
||||
&mut binary_ops,
|
||||
&mut unary_ops,
|
||||
&mut scalar_binary_ops,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub(crate) mod test_op_sequence;
|
||||
@@ -0,0 +1,16 @@
|
||||
use crate::integer::gpu::server_key::radix::tests_long_run::test_signed_random_op_sequence::signed_random_op_sequence_generic;
|
||||
use crate::integer::gpu::server_key::radix::tests_unsigned::create_gpu_parameterized_test;
|
||||
use crate::integer::server_key::radix_parallel::tests_long_run::NB_TESTS_SHORT_RUN;
|
||||
use crate::shortint::parameters::{
|
||||
TestParameters, PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
|
||||
};
|
||||
|
||||
create_gpu_parameterized_test!(signed_random_op_sequence {
|
||||
PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128
|
||||
});
|
||||
fn signed_random_op_sequence<P>(param: P)
|
||||
where
|
||||
P: Into<TestParameters> + Clone,
|
||||
{
|
||||
signed_random_op_sequence_generic(param, NB_TESTS_SHORT_RUN);
|
||||
}
|
||||
@@ -4,3 +4,4 @@ pub(crate) mod test_signed_erc20;
|
||||
pub(crate) mod test_signed_random_op_sequence;
|
||||
pub(crate) const NB_CTXT_LONG_RUN: usize = 32;
|
||||
pub(crate) const NB_TESTS_LONG_RUN: usize = 20000;
|
||||
pub(crate) const NB_TESTS_SHORT_RUN: usize = 20;
|
||||
|
||||
@@ -479,6 +479,7 @@ where
|
||||
|
||||
signed_random_op_sequence_test(
|
||||
param,
|
||||
NB_TESTS_LONG_RUN,
|
||||
&mut binary_ops,
|
||||
&mut unary_ops,
|
||||
&mut scalar_binary_ops,
|
||||
@@ -498,6 +499,7 @@ where
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn signed_random_op_sequence_test<P>(
|
||||
param: P,
|
||||
num_iterations: usize,
|
||||
binary_ops: &mut [(SignedBinaryOpExecutor, impl Fn(i64, i64) -> i64, String)],
|
||||
unary_ops: &mut [(SignedUnaryOpExecutor, impl Fn(i64) -> i64, String)],
|
||||
scalar_binary_ops: &mut [(
|
||||
@@ -646,7 +648,7 @@ pub(crate) fn signed_random_op_sequence_test<P>(
|
||||
.iter()
|
||||
.map(|&m| cks.encrypt_signed(m)) // Generate random i64 values
|
||||
.collect();
|
||||
for fn_index in 0..NB_TESTS_LONG_RUN {
|
||||
for fn_index in 0..num_iterations {
|
||||
let i = rng.gen_range(0..total_num_ops);
|
||||
let j = rng.gen_range(0..total_num_ops);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user