Compare commits

..

1 Commits

Author SHA1 Message Date
Theo Souchon
47e75759c9 chore(bench): use the bench spec for erc7984 and dex in hlapi 2026-04-20 14:16:16 +02:00
89 changed files with 1263 additions and 3673 deletions

View File

@@ -23,7 +23,7 @@ on:
# Allows you to run this workflow manually from the Actions tab as an alternative.
workflow_dispatch:
pull_request:
types: [ labeled, opened, synchronize ]
types: [ labeled ]
permissions:
contents: read
@@ -38,7 +38,6 @@ jobs:
pull-requests: read # Needed to check for file change
outputs:
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
steps:
- name: Checkout tfhe-rs
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
@@ -63,16 +62,15 @@ jobs:
- tfhe/src/integer/server_key/radix_parallel/tests_cases_unsigned.rs
- tfhe/src/shortint/parameters/**
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_core_h100_tests.yml'
core_crypto:
- tfhe/src/core_crypto/gpu/**
setup-instance:
name: gpu_core_h100_tests/setup-instance
needs: should-run
if: github.event_name != 'pull_request' ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
runs-on: ubuntu-latest
outputs:
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}

View File

@@ -23,7 +23,7 @@ on:
# Allows you to run this workflow manually from the Actions tab as an alternative.
workflow_dispatch:
pull_request:
types: [ labeled, opened, synchronize ]
types: [ labeled ]
permissions:
contents: read
@@ -38,7 +38,6 @@ jobs:
pull-requests: read # Needed to check for file change
outputs:
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
steps:
- name: Checkout tfhe-rs
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
@@ -66,15 +65,13 @@ jobs:
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_hlapi_h100_tests.yml'
core_crypto:
- tfhe/src/core_crypto/gpu/**
setup-instance:
name: gpu_hlapi_h100_tests/setup-instance
needs: should-run
if: github.event_name != 'pull_request' ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
runs-on: ubuntu-latest
outputs:
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}

View File

@@ -17,8 +17,8 @@ on:
# Allows you to run this workflow manually from the Actions tab as an alternative.
workflow_dispatch:
schedule:
# Weekly tests will be triggered every Monday at 8p.m.
- cron: "0 20 * * 1"
# Nightly tests will be triggered each evening 8p.m.
- cron: "0 20 * * *"
pull_request:
@@ -28,41 +28,10 @@ permissions:
# zizmor: ignore[concurrency-limits] concurrency is managed after instance setup to ensure safe provisioning
jobs:
should-run:
name: gpu_integer_long_run_tests/should-run
runs-on: ubuntu-latest
permissions:
pull-requests: read # Needed to check for file change
outputs:
is_needed_in_gpu_ci: ${{ env.IS_PR == 'false' || steps.changed-files.outputs.gpu_any_changed }}
steps:
- name: Checkout tfhe-rs
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0
persist-credentials: 'false'
token: ${{ env.CHECKOUT_TOKEN }}
- name: Check for file changes
id: changed-files
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
with:
files_yaml: |
gpu:
- tfhe/Cargo.toml
- tfhe/build.rs
- backends/tfhe-cuda-backend/**
- tfhe/src/core_crypto/gpu/**
- tfhe/src/integer/gpu/**
- tfhe/src/shortint/parameters/**
- '.github/workflows/gpu_integer_long_run_tests.yml'
setup-instance:
name: gpu_integer_long_run_tests/setup-instance
needs: [should-run]
if: github.event_name == 'workflow_dispatch' ||
(github.event_name == 'schedule' && github.repository == 'zama-ai/tfhe-rs') ||
needs.should-run.outputs.is_needed_in_gpu_ci == 'true'
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 }}

View File

@@ -131,10 +131,6 @@ jobs:
env:
GCC_VERSION: ${{ matrix.gcc }}
- name: Run semgrep and lint checks on CUDA code
run: |
make semgrep_and_lint_gpu_code
- name: Run fmt checks
run: |
make check_fmt_gpu
@@ -143,6 +139,10 @@ jobs:
run: |
make pcc_gpu
- name: Run semgrep and lint checks on CUDA code
run: |
make semgrep_and_lint_gpu_code
- name: Run semver checks on tfhe-cuda-backend
run: |
make semver_check_cuda_backend

View File

@@ -63,6 +63,7 @@ jobs:
- tfhe/src/shortint/parameters/**
- tfhe/src/high_level_api/**
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_signed_integer_classic_tests.yml'
- scripts/integer-tests.sh

View File

@@ -23,7 +23,7 @@ on:
# Allows you to run this workflow manually from the Actions tab as an alternative.
workflow_dispatch:
pull_request:
types: [ labeled, opened, synchronize ]
types: [ labeled ]
permissions:
contents: read
@@ -38,7 +38,6 @@ jobs:
pull-requests: read # Needed to check for file change
outputs:
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
steps:
- name: Checkout tfhe-rs
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
@@ -64,17 +63,16 @@ jobs:
- tfhe/src/shortint/parameters/**
- tfhe/src/high_level_api/**
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_signed_integer_h100_tests.yml'
- scripts/integer-tests.sh
core_crypto:
- tfhe/src/core_crypto/gpu/**
setup-instance:
name: gpu_signed_integer_h100_tests/setup-instance
needs: should-run
if: github.event_name != 'pull_request' ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
runs-on: ubuntu-latest
outputs:
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}

View File

@@ -64,6 +64,7 @@ jobs:
- tfhe/src/shortint/parameters/**
- tfhe/src/high_level_api/**
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_signed_integer_tests.yml'
- scripts/integer-tests.sh

View File

@@ -63,6 +63,7 @@ jobs:
- tfhe/src/shortint/parameters/**
- tfhe/src/high_level_api/**
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_unsigned_integer_classic_tests.yml'
- scripts/integer-tests.sh

View File

@@ -23,7 +23,7 @@ on:
# Allows you to run this workflow manually from the Actions tab as an alternative.
workflow_dispatch:
pull_request:
types: [ labeled, opened, synchronize ]
types: [ labeled ]
permissions:
contents: read
@@ -38,7 +38,6 @@ jobs:
pull-requests: read # Needed to check for file change
outputs:
gpu_test: ${{ env.IS_PULL_REQUEST == 'false' || steps.changed-files.outputs.gpu_any_changed }}
core_crypto_changed: ${{ steps.changed-files.outputs.core_crypto_any_changed }}
steps:
- name: Checkout tfhe-rs
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
@@ -64,17 +63,16 @@ jobs:
- tfhe/src/shortint/parameters/**
- tfhe/src/high_level_api/**
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_unsigned_integer_h100_tests.yml'
- scripts/integer-tests.sh
core_crypto:
- tfhe/src/core_crypto/gpu/**
setup-instance:
name: gpu_unsigned_integer_h100_tests/setup-instance
needs: should-run
if: github.event_name == 'workflow_dispatch' ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action != 'labeled' && needs.should-run.outputs.core_crypto_changed == 'true')
(github.event.action != 'labeled' && needs.should-run.outputs.gpu_test == 'true') ||
(github.event.action == 'labeled' && github.event.label.name == 'approved' && needs.should-run.outputs.gpu_test == 'true')
runs-on: ubuntu-latest
outputs:
runner-name: ${{ steps.start-remote-instance.outputs.label || steps.start-github-instance.outputs.runner_group }}

View File

@@ -64,6 +64,7 @@ jobs:
- tfhe/src/shortint/parameters/**
- tfhe/src/high_level_api/**
- tfhe/src/c_api/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_unsigned_integer_tests.yml'
- scripts/integer-tests.sh

View File

@@ -55,9 +55,12 @@ jobs:
- tfhe/build.rs
- backends/tfhe-cuda-backend/**
- backends/zk-cuda-backend/**
- tfhe/src/core_crypto/gpu/**
- tfhe/src/integer/gpu/**
- tfhe/src/shortint/parameters/**
- tfhe/src/zk/**
- tfhe-zk-pok/**
- 'tfhe/docs/**/**.md'
- '.github/workflows/gpu_zk_tests.yml'
- ci/slab.toml

View File

@@ -312,7 +312,7 @@ semgrep_and_lint_gpu_code: semgrep_lint_setup_venv
find "$(TFHECUDA_SRC)" -name '*.h' -o -name '*.cuh' -o -name '*.cu' \
| grep -v '/cmake-build-debug/' \
| grep -v '/build/' \
| xargs venv/bin/semgrep --error --config "$(TFHECUDA_SRC)/.semgrep/release-ordering.yaml" --scan-unknown-extensions
| xargs venv/bin/semgrep --config "$(TFHECUDA_SRC)/.semgrep/release-ordering.yaml" --scan-unknown-extensions
venv/bin/python3 "scripts/check_scratch_cleanup.py"
.PHONY: semver_check_cuda_backend # Run semver checks on tfhe-cuda-backend
@@ -587,17 +587,6 @@ clippy_backward_compat_data: install_rs_check_toolchain # the toolchain is selec
echo "Cannot run clippy for backward compat crate on non x86 platform for now."; \
fi
.PHONY: check_backward_compat_locks_did_not_change # Check backward compat Cargo.lock files are up to date
check_backward_compat_locks_did_not_change: install_rs_check_toolchain
@for crate in `ls -1 $(BACKWARD_COMPAT_DATA_DIR)/crates/ | grep generate_`; do \
echo "checking Cargo.lock for $$crate"; \
cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" -Z unstable-options \
-C $(BACKWARD_COMPAT_DATA_DIR)/crates/$$crate metadata --locked --format-version 1 > /dev/null || \
( echo "Cargo.lock for $$crate is out of date. Update it with:" && \
echo " cd $(BACKWARD_COMPAT_DATA_DIR)/crates/$$crate && cargo metadata --format-version 1 > /dev/null" && \
echo "then commit the updated Cargo.lock." && exit 1 ); \
done
.PHONY: clippy_test_vectors # Run clippy lints on the test vectors app
clippy_test_vectors: install_rs_check_toolchain
cd apps/test-vectors; RUSTFLAGS="$(RUSTFLAGS)" cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" clippy --all-targets \
@@ -2276,7 +2265,6 @@ pcc_batch_5:
$(call run_recipe_with_details,clippy_tfhe_lints)
$(call run_recipe_with_details,check_compile_tests)
$(call run_recipe_with_details,clippy_backward_compat_data)
$(call run_recipe_with_details,check_backward_compat_locks_did_not_change)
.PHONY: pcc_batch_6 # duration: 6'32''
pcc_batch_6:

View File

@@ -390,7 +390,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
XOR(&wires_a[6], &wires_a[15], &input_bits[7]);
XOR(&wires_a[10], &wires_a[15], &wires_b[0]);
XOR(&wires_a[11], &wires_a[20], &wires_a[9]);
FLUSH(&wires_a[6], &wires_a[10], &wires_a[11]);
FLUSH(&wires_a[6], &wires_a[10]);
XOR(&wires_a[7], &input_bits[7], &wires_a[11]);
FLUSH(&wires_a[7]);
XOR(&wires_a[17], &wires_a[10], &wires_a[11]);
@@ -426,7 +426,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
XOR(&wires_b[22], &wires_b[18], &wires_a[19]);
XOR(&wires_b[23], &wires_b[19], &wires_a[21]);
XOR(&wires_b[24], &wires_b[20], &wires_a[18]);
FLUSH(&wires_b[21], &wires_b[22], &wires_b[23], &wires_b[24]);
FLUSH(&wires_b[21], &wires_b[23], &wires_b[24]);
XOR(&wires_b[25], &wires_b[21], &wires_b[22]);
FLUSH(&wires_b[25]);
@@ -468,7 +468,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
XOR(&wires_b[37], &wires_b[36], &wires_b[34]);
XOR(&wires_b[38], &wires_b[27], &wires_b[36]);
FLUSH(&wires_b[38], &wires_b[37]);
FLUSH(&wires_b[38]);
XOR(&wires_b[44], &wires_b[33], &wires_b[37]);
CudaRadixCiphertextFFI *and_outs_6[] = {&wires_b[39]};
@@ -479,7 +479,7 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
XOR(&wires_b[40], &wires_b[25], &wires_b[39]);
XOR(&wires_b[41], &wires_b[40], &wires_b[37]);
XOR(&wires_b[43], &wires_b[29], &wires_b[40]);
FLUSH(&wires_b[41], &wires_b[40], &wires_b[43], &wires_b[44]);
FLUSH(&wires_b[41]);
XOR(&wires_b[45], &wires_b[42], &wires_b[41]);
FLUSH(&wires_b[45]);
@@ -514,7 +514,6 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
XOR(&wires_b[57], &wires_b[50], &wires_b[53]);
XOR(&wires_b[58], &wires_c[4], &wires_b[46]);
XOR(&wires_b[59], &wires_c[3], &wires_b[54]);
FLUSH(&wires_b[57], &wires_b[58]);
XOR(&wires_b[60], &wires_b[46], &wires_b[57]);
XOR(&wires_b[61], &wires_c[14], &wires_b[57]);
XOR(&wires_b[62], &wires_b[52], &wires_b[58]);
@@ -590,7 +589,6 @@ __host__ void vectorized_sbox_n_bytes(CudaStreams streams,
#undef FLUSH
#undef AND
#undef ADD_ONE_FLUSH
#undef ADD_ONE
}
/**

View File

@@ -489,7 +489,7 @@ template <typename Torus>
__host__ void host_modulus_switch_multi_bit(
cudaStream_t stream, uint32_t gpu_index, Torus *array_out, Torus *array_in,
int size, uint32_t log_modulus, uint32_t degree, uint32_t grouping_factor) {
check_cuda_error(cudaSetDevice(gpu_index));
cudaSetDevice(gpu_index);
int multibit_size = size / grouping_factor;
int num_threads = 0, num_blocks = 0;
getNumBlocksAndThreads(multibit_size, 1024, num_blocks, num_threads);

View File

@@ -308,7 +308,6 @@ void cleanup_cuda_multi_bit_programmable_bootstrap_noise_tests_128(
void *stream, uint32_t gpu_index, int8_t **pbs_buffer) {
cleanup_cuda_multi_bit_programmable_bootstrap_128(stream, gpu_index,
pbs_buffer);
cuda_synchronize_stream(static_cast<cudaStream_t>(stream), gpu_index);
}
// Noise tests variant of the 128-bit multi-bit PBS, restricted to

View File

@@ -1,6 +1,6 @@
[package]
name = "tfhe-hpu-backend"
version = "0.5.0"
version = "0.4.0"
edition = "2021"
license = "BSD-3-Clause-Clear"
description = "HPU implementation on FPGA of TFHE-rs primitives."
@@ -36,7 +36,7 @@ thiserror = "1.0.61"
bytemuck = { workspace = true }
anyhow = "1.0.82"
lazy_static = "1.4.0"
rand = "0.10.1"
rand = "0.8.5"
regex = "1.10.4"
bitflags = { version = "2.5.0", features = ["serde"] }
itertools = "0.11.0"

View File

@@ -24,7 +24,7 @@ use mem_alloc::{MemAlloc, MemChunk};
mod qdma;
use qdma::QdmaDriver;
use rand::RngExt;
use rand::Rng;
const DMA_XFER_ALIGN: usize = 4096_usize;
@@ -148,8 +148,8 @@ impl HpuHw {
tracing::debug!("Load stage1 through JTAG");
let pdi_stg1_tmp = format!(
"hpu_stg1_{}.pdi",
rand::rng()
.sample_iter(rand::distr::Alphanumeric)
rand::thread_rng()
.sample_iter(rand::distributions::Alphanumeric)
.take(5)
.map(char::from)
.collect::<String>()

View File

@@ -16,14 +16,19 @@ tfhe = { path = "../../tfhe", features = ["hpu", "hpu-debug"] }
ipc-channel = "0.18.3"
strum = { version = "0.26.2", features = ["derive"] }
strum_macros = "0.26.2"
bytemuck = { workspace = true }
clap = { version = "4.4.4", features = ["derive"] }
clap-num = "*"
anyhow = "1.0.82"
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json"] }
serde_json = "1.0"
rand = "0.8.5"
serde = { version = "1", features = ["derive"] }
bitflags = "2.6.0"
[[bin]]
name = "hpu_mockup"

View File

@@ -36,12 +36,12 @@ pub fn bench_fhe_type_op<FheType, Op>(
let inputs = op.setup_inputs(client_key, &mut rng);
let bench_type = get_bench_type();
let benchmark_spec = BenchmarkSpec::new_hlapi(
let benchmark_spec = BenchmarkSpec::new_hlapi_ops(
hlapi_op,
&param_name,
&operand_type,
Some(type_name),
bench_type,
*bench_type,
bench_backend_from_cfg(),
);
let bench_id = benchmark_spec.to_string();

View File

@@ -5,12 +5,12 @@ use benchmark::params_aliases::{
BENCH_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
BENCH_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
};
use benchmark::utilities::{bench_backend_from_cfg, write_to_json, OperatorType};
#[cfg(feature = "gpu")]
use benchmark::utilities::{configure_gpu, get_param_type, ParamType};
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
use benchmark_spec::{get_bench_type, BenchmarkType};
use criterion::measurement::WallTime;
use criterion::{BenchmarkGroup, Criterion, Throughput};
use benchmark_spec::tfhe::hlapi::dex::{Dex, DexFlavor};
use benchmark_spec::{get_bench_type, BenchmarkMetric, BenchmarkSpec, BenchmarkType, OperandType};
use criterion::{Criterion, Throughput};
use rand::prelude::*;
use rand::thread_rng;
use rayon::prelude::*;
@@ -220,21 +220,15 @@ where
#[cfg(feature = "pbs-stats")]
mod pbs_stats {
use super::*;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
fn write_result(file: &mut File, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
file.write_all(line.as_bytes()).expect(&error_message);
}
use benchmark_spec::TestResult;
use super::*;
pub fn print_swap_request_update_dex_balance_pbs_counts<FheType, F>(
client_key: &ClientKey,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_request_update_dex_balance_func: F,
) where
FheType: FheEncrypt<u64, ClientKey>,
@@ -258,29 +252,24 @@ mod pbs_stats {
let params = client_key.computation_parameters();
let params_name = params.name();
let test_name = if cfg!(feature = "gpu") {
format!("hlapi::cuda::dex::pbs_count::swap_request_update_dex_balance::{fn_name}::{params_name}::{type_name}")
} else {
format!(
"hlapi::dex::pbs_count::swap_request_update_dex_balance::{fn_name}::{params_name}::{type_name}"
)
};
let test_name = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::PbsCount,
bench_backend_from_cfg(),
None,
);
let results_file = Path::new("dex_swap_request_update_dex_balance_pbs_count.csv");
if !results_file.exists() {
File::create(results_file).expect("create results file failed");
}
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result =
TestResult::new("dex_swap_request_update_dex_balance_pbs_count.csv");
write_result(&mut file, &test_name, count as usize);
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
write_to_json_unchecked::<u64, _>(
write_to_json::<u64, _>(
&test_name,
params,
params_name,
"pbs-count",
&OperatorType::Atomic,
0,
@@ -290,6 +279,7 @@ mod pbs_stats {
pub fn print_swap_request_finalize_pbs_counts<FheType, F>(
client_key: &ClientKey,
type_name: &str,
fn_name: Dex,
swap_request_finalize_func: F,
) where
FheType: FheEncrypt<u64, ClientKey>,
@@ -313,29 +303,23 @@ mod pbs_stats {
let params = client_key.computation_parameters();
let params_name = params.name();
let test_name = if cfg!(feature = "gpu") {
format!(
"hlapi::cuda::dex::pbs_count::swap_request_finalize::{params_name}::{type_name}"
)
} else {
format!("hlapi::dex::pbs_count::swap_request_finalize::{params_name}::{type_name}")
};
let test_name = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::PbsCount,
bench_backend_from_cfg(),
None,
);
let results_file = Path::new("dex_swap_request_finalize_pbs_count.csv");
if !results_file.exists() {
File::create(results_file).expect("create results file failed");
}
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::new("dex_swap_request_finalize_pbs_count.csv");
write_result(&mut file, &test_name, count as usize);
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
write_to_json_unchecked::<u64, _>(
write_to_json::<u64, _>(
&test_name,
params,
params_name,
"pbs-count",
&OperatorType::Atomic,
0,
@@ -345,6 +329,7 @@ mod pbs_stats {
pub fn print_swap_claim_prepare_pbs_counts<FheType, F>(
client_key: &ClientKey,
type_name: &str,
fn_name: Dex,
swap_claim_prepare_func: F,
) where
FheType: FheEncrypt<u64, ClientKey>,
@@ -378,27 +363,23 @@ mod pbs_stats {
let params = client_key.computation_parameters();
let params_name = params.name();
let test_name = if cfg!(feature = "gpu") {
format!("hlapi::cuda::pbs_count::dex::swap_claim_prepare::{params_name}::{type_name}")
} else {
format!("hlapi::dex::pbs_count::swap_claim_prepare::{params_name}::{type_name}")
};
let test_name = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::PbsCount,
bench_backend_from_cfg(),
None,
);
let results_file = Path::new("dex_swap_claim_prepare_pbs_count.csv");
if !results_file.exists() {
File::create(results_file).expect("create results file failed");
}
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::new("dex_swap_claim_prepare_pbs_count.csv");
write_result(&mut file, &test_name, count as usize);
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
write_to_json_unchecked::<u64, _>(
write_to_json::<u64, _>(
&test_name,
params,
params_name,
"pbs-count",
&OperatorType::Atomic,
0,
@@ -408,7 +389,7 @@ mod pbs_stats {
pub fn print_swap_claim_update_dex_balance_pbs_counts<FheType, F>(
client_key: &ClientKey,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_claim_update_dex_balance_func: F,
) where
FheType: FheEncrypt<u64, ClientKey>,
@@ -438,27 +419,24 @@ mod pbs_stats {
let params = client_key.computation_parameters();
let params_name = params.name();
let test_name = if cfg!(feature = "gpu") {
format!("hlapi::cuda::pbs_count::dex::swap_claim_update_dex_balance::{fn_name}::{params_name}::{type_name}")
} else {
format!("hlapi::dex::pbs_count::swap_claim_update_dex_balance::{fn_name}::{params_name}::{type_name}")
};
let test_name = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::PbsCount,
bench_backend_from_cfg(),
None,
);
let results_file = Path::new("dex_swap_claim_update_dex_balance_pbs_count.csv");
if !results_file.exists() {
File::create(results_file).expect("create results file failed");
}
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result =
TestResult::new("dex_swap_claim_update_dex_balance_pbs_count.csv");
write_result(&mut file, &test_name, count as usize);
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
write_to_json_unchecked::<u64, _>(
write_to_json::<u64, _>(
&test_name,
params,
params_name,
"pbs-count",
&OperatorType::Atomic,
0,
@@ -468,11 +446,10 @@ mod pbs_stats {
}
fn bench_swap_request_latency<FheType, F1, F2>(
c: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_request_update_dex_balance_func: F1,
swap_request_finalize_func: F2,
) where
@@ -486,8 +463,19 @@ fn bench_swap_request_latency<FheType, F1, F2>(
let params = client_key.computation_parameters();
let params_name = params.name();
let bench_id = format!("{bench_name}::{fn_name}::{type_name}");
c.bench_function(&bench_id, |b| {
let mut c = c.benchmark_group(type_name);
let bench_spec = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Latency,
bench_backend_from_cfg(),
None,
);
c.bench_function(bench_spec.to_string(), |b| {
let mut rng = thread_rng();
let from_balance_0 = FheType::encrypt(rng.gen::<u64>(), client_key);
@@ -525,10 +513,9 @@ fn bench_swap_request_latency<FheType, F1, F2>(
})
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
params_name,
"dex-swap-request",
&OperatorType::Atomic,
64,
@@ -538,11 +525,10 @@ fn bench_swap_request_latency<FheType, F1, F2>(
#[cfg(not(feature = "gpu"))]
fn bench_swap_request_throughput<FheType, F1, F2>(
group: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_request_update_dex_balance_func: F1,
swap_request_finalize_func: F2,
) where
@@ -555,12 +541,22 @@ fn bench_swap_request_throughput<FheType, F1, F2>(
let params = client_key.computation_parameters();
let params_name = params.name();
let mut group = c.benchmark_group(type_name);
for num_elems in [10, 50, 100] {
group.throughput(Throughput::Elements(num_elems));
let bench_id = format!(
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
let bench_spec = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(num_elems.try_into().unwrap()),
);
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
let from_balances_0 = (0..num_elems)
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
.collect::<Vec<_>>();
@@ -641,10 +637,9 @@ fn bench_swap_request_throughput<FheType, F1, F2>(
})
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"dex-swap-request",
&OperatorType::Atomic,
64,
@@ -654,11 +649,10 @@ fn bench_swap_request_throughput<FheType, F1, F2>(
}
#[cfg(feature = "gpu")]
fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
group: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_request_update_dex_balance_func: F1,
swap_request_finalize_func: F2,
) where
@@ -678,12 +672,20 @@ fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
let params = client_key.computation_parameters();
let params_name = params.name();
let mut group = c.benchmark_group(type_name);
for num_elems in [5 * num_gpus, 10 * num_gpus, 20 * num_gpus] {
group.throughput(Throughput::Elements(num_elems));
let bench_id = format!(
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
let bench_spec = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(num_elems.try_into().unwrap()),
);
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
let from_balances_0 = (0..num_elems)
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
.collect::<Vec<_>>();
@@ -853,10 +855,9 @@ fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
})
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"dex-swap-request",
&OperatorType::Atomic,
64,
@@ -866,11 +867,10 @@ fn cuda_bench_swap_request_throughput<FheType, F1, F2>(
}
fn bench_swap_claim_latency<FheType, F1, F2>(
c: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_claim_prepare_func: F1,
swap_claim_update_dex_balance_func: F2,
) where
@@ -884,8 +884,19 @@ fn bench_swap_claim_latency<FheType, F1, F2>(
let params = client_key.computation_parameters();
let params_name = params.name();
let bench_id = format!("{bench_name}::{fn_name}::{params_name}::{type_name}");
c.bench_function(&bench_id, |b| {
let mut c = c.benchmark_group(type_name);
let bench_spec = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Latency,
bench_backend_from_cfg(),
None,
);
c.bench_function(bench_spec.to_string(), |b| {
let mut rng = thread_rng();
let pending_0_in = FheType::encrypt(rng.gen::<u64>(), client_key);
@@ -929,10 +940,9 @@ fn bench_swap_claim_latency<FheType, F1, F2>(
});
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"dex-swap-claim",
&OperatorType::Atomic,
64,
@@ -942,11 +952,10 @@ fn bench_swap_claim_latency<FheType, F1, F2>(
#[cfg(not(feature = "gpu"))]
fn bench_swap_claim_throughput<FheType, F1, F2>(
group: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_claim_prepare_func: F1,
swap_claim_update_dex_balance_func: F2,
) where
@@ -959,12 +968,22 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
let params = client_key.computation_parameters();
let params_name = params.name();
let mut group = c.benchmark_group(type_name);
for num_elems in [2, 6, 10] {
group.throughput(Throughput::Elements(num_elems));
let bench_id = format!(
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
let bench_spec = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(num_elems.try_into().unwrap()),
);
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
let pending_0_in = (0..num_elems)
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
.collect::<Vec<_>>();
@@ -1063,10 +1082,9 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
});
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"dex-swap-claim",
&OperatorType::Atomic,
64,
@@ -1076,11 +1094,10 @@ fn bench_swap_claim_throughput<FheType, F1, F2>(
}
#[cfg(feature = "gpu")]
fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
group: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Dex,
swap_claim_prepare_func: F1,
swap_claim_update_dex_balance_func: F2,
) where
@@ -1100,12 +1117,20 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
let params = client_key.computation_parameters();
let params_name = params.name();
let mut group = c.benchmark_group(type_name);
for num_elems in [num_gpus, 2 * num_gpus] {
group.throughput(Throughput::Elements(num_elems));
let bench_id = format!(
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
let bench_spec = BenchmarkSpec::new_hlapi_dex(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(num_elems.try_into().unwrap()),
);
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
let pending_0_in = (0..num_elems)
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
.collect::<Vec<_>>();
@@ -1270,10 +1295,9 @@ fn cuda_bench_swap_claim_throughput<FheType, F1, F2>(
});
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"dex-swap-claim",
&OperatorType::Atomic,
64,
@@ -1306,8 +1330,6 @@ fn main() {
let mut c = Criterion::default().sample_size(10).configure_from_args();
let bench_name = "hlapi::dex";
// FheUint64 PBS counts
// We don't run multiple times since every input is encrypted
// PBS count is always the same
@@ -1316,120 +1338,109 @@ fn main() {
print_swap_request_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"whitepaper",
Dex::SwapRequest(DexFlavor::Whitepaper),
swap_request_update_dex_balance_whitepaper::<FheUint64>,
);
print_swap_request_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"no_cmux",
Dex::SwapRequest(DexFlavor::NoCmux),
swap_request_update_dex_balance_no_cmux::<FheUint64>,
);
print_swap_request_finalize_pbs_counts(
&cks,
"FheUint64",
Dex::SwapRequest(DexFlavor::Finalize),
swap_request_finalize::<FheUint64>,
);
print_swap_claim_prepare_pbs_counts(
&cks,
"FheUint64",
Dex::SwapClaim(DexFlavor::Prepare),
swap_claim_prepare::<FheUint64, FheUint128>,
);
print_swap_claim_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"whitepaper",
Dex::SwapClaim(DexFlavor::Whitepaper),
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
);
print_swap_claim_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"no_cmux",
Dex::SwapClaim(DexFlavor::NoCmux),
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
);
}
match get_bench_type() {
BenchmarkType::Latency => {
let mut group = c.benchmark_group(bench_name);
bench_swap_request_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::whitepaper",
Dex::SwapRequest(DexFlavor::Whitepaper),
swap_request_update_dex_balance_whitepaper::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
bench_swap_request_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::no_cmux",
Dex::SwapRequest(DexFlavor::NoCmux),
swap_request_update_dex_balance_no_cmux::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
bench_swap_claim_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::whitepaper",
Dex::SwapClaim(DexFlavor::Whitepaper),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
);
bench_swap_claim_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::no_cmux",
Dex::SwapClaim(DexFlavor::NoCmux),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
);
group.finish();
}
BenchmarkType::Throughput => {
let mut group = c.benchmark_group(bench_name);
bench_swap_request_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::whitepaper",
Dex::SwapRequest(DexFlavor::Whitepaper),
swap_request_update_dex_balance_whitepaper::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
bench_swap_request_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::no_cmux",
Dex::SwapRequest(DexFlavor::NoCmux),
swap_request_update_dex_balance_no_cmux::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
bench_swap_claim_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::whitepaper",
Dex::SwapClaim(DexFlavor::Whitepaper),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
);
bench_swap_claim_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::no_cmux",
Dex::SwapClaim(DexFlavor::NoCmux),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
);
group.finish();
}
};
@@ -1449,8 +1460,6 @@ fn main() {
let mut c = Criterion::default().sample_size(10).configure_from_args();
let bench_name = "hlapi::cuda::dex";
// FheUint64 PBS counts
// We don't run multiple times since every input is encrypted
// PBS count is always the same
@@ -1459,121 +1468,110 @@ fn main() {
print_swap_request_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"whitepaper",
Dex::SwapRequest(DexFlavor::Whitepaper),
swap_request_update_dex_balance_whitepaper::<FheUint64>,
);
print_swap_request_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"no_cmux",
Dex::SwapRequest(DexFlavor::NoCmux),
swap_request_update_dex_balance_no_cmux::<FheUint64>,
);
print_swap_request_finalize_pbs_counts(
&cks,
"FheUint64",
Dex::SwapRequest(DexFlavor::Finalize),
swap_request_finalize::<FheUint64>,
);
print_swap_claim_prepare_pbs_counts(
&cks,
"FheUint64",
Dex::SwapClaim(DexFlavor::Prepare),
swap_claim_prepare::<FheUint64, FheUint128>,
);
print_swap_claim_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"whitepaper",
Dex::SwapClaim(DexFlavor::Whitepaper),
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
);
print_swap_claim_update_dex_balance_pbs_counts(
&cks,
"FheUint64",
"no_cmux",
Dex::SwapClaim(DexFlavor::NoCmux),
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
);
}
match get_bench_type() {
BenchmarkType::Latency => {
let mut group = c.benchmark_group(bench_name);
bench_swap_request_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::whitepaper",
Dex::SwapRequest(DexFlavor::Whitepaper),
swap_request_update_dex_balance_whitepaper::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
bench_swap_request_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::no_cmux",
Dex::SwapRequest(DexFlavor::NoCmux),
swap_request_update_dex_balance_no_cmux::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
bench_swap_claim_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::whitepaper",
Dex::SwapClaim(DexFlavor::Whitepaper),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
);
bench_swap_claim_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::no_cmux",
Dex::SwapClaim(DexFlavor::NoCmux),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
);
group.finish();
}
BenchmarkType::Throughput => {
let mut group = c.benchmark_group(bench_name);
cuda_bench_swap_request_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::whitepaper",
Dex::SwapRequest(DexFlavor::Whitepaper),
swap_request_update_dex_balance_whitepaper::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
cuda_bench_swap_request_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_request::no_cmux",
Dex::SwapRequest(DexFlavor::NoCmux),
swap_request_update_dex_balance_no_cmux::<FheUint64>,
swap_request_finalize::<FheUint64>,
);
cuda_bench_swap_claim_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::whitepaper",
Dex::SwapClaim(DexFlavor::Whitepaper),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_whitepaper::<FheUint64>,
);
cuda_bench_swap_claim_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"swap_claim::no_cmux",
Dex::SwapClaim(DexFlavor::NoCmux),
swap_claim_prepare::<FheUint64, FheUint128>,
swap_claim_update_dex_balance_no_cmux::<FheUint64>,
);
group.finish();
}
};

View File

@@ -1,9 +1,9 @@
use benchmark::utilities::{bench_backend_from_cfg, write_to_json, OperatorType};
#[cfg(feature = "gpu")]
use benchmark::utilities::{configure_gpu, get_param_type, ParamType};
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
use benchmark_spec::{get_bench_type, BenchmarkType};
use criterion::measurement::WallTime;
use criterion::{BenchmarkGroup, Criterion, Throughput};
use benchmark_spec::tfhe::hlapi::erc7984::{Erc7984, TransferFlavor};
use benchmark_spec::{get_bench_type, BenchmarkMetric, BenchmarkSpec, BenchmarkType, OperandType};
use criterion::{Criterion, Throughput};
use rand::prelude::*;
use rand::thread_rng;
#[cfg(not(feature = "hpu"))]
@@ -286,21 +286,14 @@ where
#[cfg(all(feature = "pbs-stats", not(feature = "hpu")))]
mod pbs_stats {
use super::*;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
use benchmark_spec::TestResult;
fn write_result(file: &mut File, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
file.write_all(line.as_bytes()).expect(&error_message);
}
use super::*;
pub fn print_transfer_pbs_counts<FheType, F>(
client_key: &ClientKey,
type_name: &str,
fn_name: &str,
fn_name: Erc7984,
transfer_func: F,
) where
FheType: FheEncrypt<u64, ClientKey>,
@@ -324,27 +317,23 @@ mod pbs_stats {
let params = client_key.computation_parameters();
let params_name = params.name();
let test_name = if cfg!(feature = "gpu") {
format!("hlapi::cuda::erc7984::pbs_count::{fn_name}::{params_name}::{type_name}")
} else {
format!("hlapi::erc7984::pbs_count::{fn_name}::{params_name}::{type_name}")
};
let test_name = BenchmarkSpec::new_hlapi_erc7984(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::PbsCount,
bench_backend_from_cfg(),
None,
);
let results_file = Path::new("erc7984_pbs_count.csv");
if !results_file.exists() {
File::create(results_file).expect("create results file failed");
}
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::new("erc7984_pbs_count.csv");
write_result(&mut file, &test_name, count as usize);
benchmark_test_result.write_result(&test_name.to_string(), count as usize);
write_to_json_unchecked::<u64, _>(
write_to_json::<u64, _>(
&test_name,
params,
params_name,
"pbs-count",
&OperatorType::Atomic,
0,
@@ -354,11 +343,10 @@ mod pbs_stats {
}
fn bench_transfer_latency<FheType, F>(
c: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Erc7984,
transfer_func: F,
) where
FheType: FheEncrypt<u64, ClientKey>,
@@ -371,7 +359,18 @@ fn bench_transfer_latency<FheType, F>(
let params = client_key.computation_parameters();
let params_name = params.name();
let bench_id = format!("{bench_name}::{fn_name}::{params_name}::{type_name}");
let mut c = c.benchmark_group(type_name);
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Latency,
bench_backend_from_cfg(),
None,
);
let bench_id = bench_spec.to_string();
c.bench_function(&bench_id, |b| {
let mut rng = thread_rng();
@@ -388,10 +387,9 @@ fn bench_transfer_latency<FheType, F>(
})
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
params_name,
"erc7984-transfer",
&OperatorType::Atomic,
64,
@@ -401,11 +399,10 @@ fn bench_transfer_latency<FheType, F>(
#[cfg(feature = "hpu")]
fn bench_transfer_latency_simd<FheType, F>(
c: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Erc7984,
transfer_func: F,
) where
FheType: FheEncrypt<u64, ClientKey>,
@@ -423,9 +420,18 @@ fn bench_transfer_latency_simd<FheType, F>(
let params = client_key.computation_parameters();
let params_name = params.name();
let mut c = c.benchmark_group(type_name);
let bench_id = format!("{bench_name}::{fn_name}::{params_name}::{type_name}");
c.bench_function(&bench_id, |b| {
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
None,
);
c.bench_function(bench_spec.to_string(), |b| {
let mut rng = thread_rng();
let mut from_amounts: Vec<FheType> = vec![];
@@ -449,10 +455,9 @@ fn bench_transfer_latency_simd<FheType, F>(
})
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
params_name,
"erc7984-simd-transfer",
&OperatorType::Atomic,
64,
@@ -462,11 +467,10 @@ fn bench_transfer_latency_simd<FheType, F>(
#[cfg(not(any(feature = "gpu", feature = "hpu")))]
fn bench_transfer_throughput<FheType, F>(
group: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Erc7984,
transfer_func: F,
) where
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
@@ -477,11 +481,20 @@ fn bench_transfer_throughput<FheType, F>(
let params = client_key.computation_parameters();
let params_name = params.name();
let mut group = c.benchmark_group(type_name);
for num_elems in [10, 100, 500] {
group.throughput(Throughput::Elements(num_elems));
let bench_id = format!(
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(num_elems.try_into().unwrap()),
);
let bench_id = bench_spec.to_string();
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
let from_amounts = (0..num_elems)
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
@@ -503,10 +516,9 @@ fn bench_transfer_throughput<FheType, F>(
})
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"erc7984-transfer",
&OperatorType::Atomic,
64,
@@ -517,11 +529,10 @@ fn bench_transfer_throughput<FheType, F>(
#[cfg(feature = "gpu")]
fn cuda_bench_transfer_throughput<FheType, F>(
group: &mut BenchmarkGroup<'_, WallTime>,
c: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Erc7984,
transfer_func: F,
) where
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
@@ -542,11 +553,19 @@ fn cuda_bench_transfer_throughput<FheType, F>(
// and is a multiple of the number of streams per GPU to avoid a bigger batch on one stream
let num_elems = 300 * num_gpus;
let mut group = c.benchmark_group(type_name);
group.throughput(Throughput::Elements(num_elems));
let bench_id = format!(
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(num_elems.try_into().unwrap()),
);
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
let from_amounts = (0..num_elems)
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
.collect::<Vec<_>>();
@@ -593,10 +612,9 @@ fn cuda_bench_transfer_throughput<FheType, F>(
});
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"erc7984-transfer",
&OperatorType::Atomic,
64,
@@ -606,11 +624,10 @@ fn cuda_bench_transfer_throughput<FheType, F>(
#[cfg(feature = "hpu")]
fn hpu_bench_transfer_throughput<FheType, F>(
group: &mut BenchmarkGroup<'_, WallTime>,
group: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Erc7984,
transfer_func: F,
) where
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
@@ -622,12 +639,19 @@ fn hpu_bench_transfer_throughput<FheType, F>(
let params = client_key.computation_parameters();
let params_name = params.name();
let mut group = group.benchmark_group(type_name);
for num_elems in [10, 100] {
group.throughput(Throughput::Elements(num_elems));
let bench_id = format!(
"{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{num_elems}_elems"
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(num_elems.try_into().unwrap()),
);
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
let from_amounts = (0..num_elems)
.map(|_| FheType::encrypt(rng.gen::<u64>(), client_key))
.collect::<Vec<_>>();
@@ -657,10 +681,9 @@ fn hpu_bench_transfer_throughput<FheType, F>(
});
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"erc7984-transfer",
&OperatorType::Atomic,
64,
@@ -671,11 +694,10 @@ fn hpu_bench_transfer_throughput<FheType, F>(
#[cfg(feature = "hpu")]
fn hpu_bench_transfer_throughput_simd<FheType, F>(
group: &mut BenchmarkGroup<'_, WallTime>,
group: &mut Criterion,
client_key: &ClientKey,
bench_name: &str,
type_name: &str,
fn_name: &str,
fn_name: Erc7984,
transfer_func: F,
) where
FheType: FheEncrypt<u64, ClientKey> + Send + Sync,
@@ -698,9 +720,16 @@ fn hpu_bench_transfer_throughput_simd<FheType, F>(
for num_elems in [2, 8] {
let real_num_elems = num_elems * (hpu_simd_n as u64);
group.throughput(Throughput::Elements(real_num_elems));
let bench_id =
format!("{bench_name}::throughput::{fn_name}::{params_name}::{type_name}::{real_num_elems}_elems");
group.bench_with_input(&bench_id, &num_elems, |b, &num_elems| {
let bench_spec = BenchmarkSpec::new_hlapi_erc7984(
fn_name,
&params_name,
&OperandType::CipherText,
Some(type_name),
BenchmarkMetric::Throughput,
bench_backend_from_cfg(),
Some(real_num_elems.try_into().unwrap()),
);
group.bench_with_input(bench_spec.to_string(), &num_elems, |b, &num_elems| {
let from_amounts = (0..num_elems)
.map(|_| {
(0..hpu_simd_n)
@@ -742,11 +771,10 @@ fn hpu_bench_transfer_throughput_simd<FheType, F>(
});
});
write_to_json_unchecked::<u64, _>(
&bench_id,
write_to_json::<u64, _>(
&bench_spec,
params,
&params_name,
"erc7984-simd-ransfer",
"erc7984-simd-transfer",
&OperatorType::Atomic,
64,
vec![],
@@ -769,8 +797,6 @@ fn main() {
let mut c = Criterion::default().sample_size(10).configure_from_args();
let bench_name = "hlapi::erc7984";
// FheUint64 PBS counts
// We don't run multiple times since every input is encrypted
// PBS count is always the same
@@ -780,99 +806,90 @@ fn main() {
print_transfer_pbs_counts(
&cks,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
par_transfer_whitepaper::<FheUint64>,
);
print_transfer_pbs_counts(
&cks,
"FheUint64",
"no_cmux",
Erc7984::Transfer(TransferFlavor::NoCmux),
par_transfer_no_cmux::<FheUint64>,
);
print_transfer_pbs_counts(
&cks,
"FheUint64",
"transfer::overflow",
Erc7984::Transfer(TransferFlavor::Overflow),
par_transfer_overflow::<FheUint64>,
);
print_transfer_pbs_counts(&cks, "FheUint64", "safe", par_transfer_safe::<FheUint64>);
print_transfer_pbs_counts(
&cks,
"FheUint64",
Erc7984::Transfer(TransferFlavor::Safe),
par_transfer_safe::<FheUint64>,
);
}
match get_bench_type() {
BenchmarkType::Latency => {
let mut group = c.benchmark_group(bench_name);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
par_transfer_whitepaper::<FheUint64>,
);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::no_cmux",
Erc7984::Transfer(TransferFlavor::NoCmux),
par_transfer_no_cmux::<FheUint64>,
);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::overflow",
Erc7984::Transfer(TransferFlavor::Overflow),
par_transfer_overflow::<FheUint64>,
);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::safe",
Erc7984::Transfer(TransferFlavor::Safe),
par_transfer_safe::<FheUint64>,
);
group.finish();
}
BenchmarkType::Throughput => {
let mut group = c.benchmark_group(bench_name);
bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
par_transfer_whitepaper::<FheUint64>,
);
bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::no_cmux",
Erc7984::Transfer(TransferFlavor::NoCmux),
par_transfer_no_cmux::<FheUint64>,
);
bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::overflow",
Erc7984::Transfer(TransferFlavor::Overflow),
par_transfer_overflow::<FheUint64>,
);
bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::safe",
Erc7984::Transfer(TransferFlavor::Safe),
par_transfer_safe::<FheUint64>,
);
group.finish();
}
};
@@ -896,8 +913,6 @@ fn main() {
let mut c = Criterion::default().sample_size(10).configure_from_args();
let bench_name = "hlapi::cuda::erc7984";
// FheUint64 PBS counts
// We don't run multiple times since every input is encrypted
// PBS count is always the same
@@ -907,98 +922,90 @@ fn main() {
print_transfer_pbs_counts(
&cks,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
par_transfer_whitepaper::<FheUint64>,
);
print_transfer_pbs_counts(
&cks,
"FheUint64",
"no_cmux",
Erc7984::Transfer(TransferFlavor::NoCmux),
par_transfer_no_cmux::<FheUint64>,
);
print_transfer_pbs_counts(
&cks,
"FheUint64",
"transfer::overflow",
Erc7984::Transfer(TransferFlavor::Overflow),
par_transfer_overflow::<FheUint64>,
);
print_transfer_pbs_counts(&cks, "FheUint64", "safe", par_transfer_safe::<FheUint64>);
print_transfer_pbs_counts(
&cks,
"FheUint64",
Erc7984::Transfer(TransferFlavor::Safe),
par_transfer_safe::<FheUint64>,
);
}
match get_bench_type() {
BenchmarkType::Latency => {
let mut group = c.benchmark_group(bench_name);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
par_transfer_whitepaper::<FheUint64>,
);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::no_cmux",
Erc7984::Transfer(TransferFlavor::NoCmux),
par_transfer_no_cmux::<FheUint64>,
);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::overflow",
Erc7984::Transfer(TransferFlavor::Overflow),
par_transfer_overflow::<FheUint64>,
);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::safe",
Erc7984::Transfer(TransferFlavor::Safe),
par_transfer_safe::<FheUint64>,
);
group.finish();
}
BenchmarkType::Throughput => {
let mut group = c.benchmark_group(bench_name);
cuda_bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
transfer_whitepaper::<FheUint64>,
);
cuda_bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::no_cmux",
Erc7984::Transfer(TransferFlavor::NoCmux),
transfer_no_cmux::<FheUint64>,
);
cuda_bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::overflow",
Erc7984::Transfer(TransferFlavor::Overflow),
transfer_overflow::<FheUint64>,
);
cuda_bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::safe",
Erc7984::Transfer(TransferFlavor::Safe),
transfer_safe::<FheUint64>,
);
group.finish();
}
};
@@ -1027,69 +1034,57 @@ fn main() {
let mut c = Criterion::default().sample_size(10).configure_from_args();
let bench_name = "hlapi::hpu::erc7984";
match get_bench_type() {
BenchmarkType::Latency => {
let mut group = c.benchmark_group(bench_name);
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
transfer_whitepaper::<FheUint64>,
);
// Erc7984 optimized instruction only available on Hpu
bench_transfer_latency(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::hpu_optim",
Erc7984::Transfer(TransferFlavor::HpuOptim),
transfer_hpu::<FheUint64>,
);
// Erc7984 SIMD instruction only available on Hpu
bench_transfer_latency_simd(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::hpu_simd",
Erc7984::Transfer(TransferFlavor::HpuSimd),
transfer_hpu_simd::<FheUint64>,
);
group.finish();
}
BenchmarkType::Throughput => {
let mut group = c.benchmark_group(bench_name);
hpu_bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::whitepaper",
Erc7984::Transfer(TransferFlavor::Whitepaper),
transfer_whitepaper::<FheUint64>,
);
// Erc7984 optimized instruction only available on Hpu
hpu_bench_transfer_throughput(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::hpu_optim",
Erc7984::Transfer(TransferFlavor::HpuOptim),
transfer_hpu::<FheUint64>,
);
// Erc7984 SIMD instruction only available on Hpu
hpu_bench_transfer_throughput_simd(
&mut group,
&mut c,
&cks,
bench_name,
"FheUint64",
"transfer::hpu_simd",
Erc7984::Transfer(TransferFlavor::HpuSimd),
transfer_hpu_simd::<FheUint64>,
);
group.finish();
}
};

View File

@@ -1,12 +1,10 @@
use benchmark::params_aliases::*;
use benchmark::utilities::{throughput_num_threads, write_to_json_unchecked, OperatorType};
use benchmark_spec::{get_bench_type, BenchmarkType};
use benchmark_spec::{get_bench_type, BenchmarkType, TestResult};
use criterion::{criterion_group, Criterion, Throughput};
use rand::prelude::*;
use rayon::prelude::*;
use std::env;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
use tfhe::core_crypto::prelude::LweCiphertextCount;
use tfhe::integer::key_switching_key::KeySwitchingKey;
@@ -61,12 +59,6 @@ fn compute_load_config() -> Vec<ZkComputeLoad> {
conf
}
fn write_result(file: &mut File, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
file.write_all(line.as_bytes()).expect(&error_message);
}
fn zk_throughput_num_elements() -> u64 {
// Zk verify uses pools of 32 threads for a single verification
let pool_size = 32;
@@ -217,11 +209,7 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
.sample_size(15)
.measurement_time(std::time::Duration::from_secs(60));
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
for (param_pke, param_casting, param_fhe) in [(
BENCH_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
@@ -271,7 +259,8 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
let test_name =
format!("zk::crs_sizes::{param_name}::{bits}_bits_packed_ZK{zk_vers:?}");
write_result(&mut file, &test_name, crs_data.len());
benchmark_test_result.write_result(&test_name, crs_data.len());
write_to_json_unchecked::<u64, _>(
&test_name,
shortint_params,
@@ -321,11 +310,9 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
"zk::proven_list_size::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}"
);
write_result(
&mut file,
&test_name,
proven_ciphertext_list_serialized.len(),
);
benchmark_test_result
.write_result(&test_name, proven_ciphertext_list_serialized.len());
write_to_json_unchecked::<u64, _>(
&test_name,
shortint_params,
@@ -342,7 +329,8 @@ fn cpu_pke_zk_verify(c: &mut Criterion, results_file: &Path) {
let test_name =
format!("zk::proof_sizes::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}");
write_result(&mut file, &test_name, proof_size);
benchmark_test_result.write_result(&test_name, proof_size);
write_to_json_unchecked::<u64, _>(
&test_name,
shortint_params,
@@ -522,11 +510,7 @@ mod cuda {
.sample_size(15)
.measurement_time(std::time::Duration::from_secs(60));
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
let (param_pke, param_ksk, param_fhe): (
CompactPublicKeyEncryptionParameters,
@@ -590,7 +574,7 @@ mod cuda {
let test_name =
format!("zk::crs_sizes::{param_name}::{bits}_bits_packed_ZK{zk_vers:?}");
write_result(&mut file, &test_name, crs_data.len());
benchmark_test_result.write_result(&test_name, crs_data.len());
write_to_json_unchecked::<u64, _>(
&test_name,
param_fhe,
@@ -660,11 +644,8 @@ mod cuda {
"zk::proven_list_size::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}"
);
write_result(
&mut file,
&test_name,
proven_ciphertext_list_serialized.len(),
);
benchmark_test_result
.write_result(&test_name, proven_ciphertext_list_serialized.len());
write_to_json_unchecked::<u64, _>(
&test_name,
param_fhe,
@@ -681,7 +662,7 @@ mod cuda {
let test_name =
format!("zk::proof_sizes::{param_name}::{bits}_bits_packed_{crs_size}_bits_crs_{zk_load}_ZK{zk_vers:?}");
write_result(&mut file, &test_name, proof_size);
benchmark_test_result.write_result(&test_name, proof_size);
write_to_json_unchecked::<u64, _>(
&test_name,
param_fhe,

View File

@@ -1,26 +1,16 @@
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
use std::fs::{File, OpenOptions};
use std::io::Write;
use benchmark_spec::TestResult;
use std::path::Path;
use tfhe::boolean::parameters::{DEFAULT_PARAMETERS, PARAMETERS_ERROR_PROB_2_POW_MINUS_165};
use tfhe::boolean::{client_key, server_key};
fn write_result(file: &mut File, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
file.write_all(line.as_bytes()).expect(&error_message);
}
fn client_server_key_sizes(results_file: &Path) {
let boolean_params_vec = [
(DEFAULT_PARAMETERS, "DEFAULT_PARAMETERS"),
(PARAMETERS_ERROR_PROB_2_POW_MINUS_165, "TFHE_LIB_PARAMETERS"),
];
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
let operator = OperatorType::Atomic;
@@ -38,7 +28,7 @@ fn client_server_key_sizes(results_file: &Path) {
let ksk_size = sks.key_switching_key_size_bytes();
let test_name = format!("boolean_key_sizes_{params_name}_ksk");
write_result(&mut file, &test_name, ksk_size);
benchmark_test_result.write_result(&test_name, ksk_size);
write_to_json_unchecked::<u32, _>(
&test_name,
*params,
@@ -58,7 +48,7 @@ fn client_server_key_sizes(results_file: &Path) {
let bsk_size = sks.bootstrapping_key_size_bytes();
let test_name = format!("boolean_key_sizes_{params_name}_bsk");
write_result(&mut file, &test_name, bsk_size);
benchmark_test_result.write_result(&test_name, bsk_size);
write_to_json_unchecked::<u32, _>(
&test_name,
*params,

View File

@@ -1,9 +1,8 @@
use benchmark::params::{get_classical_tuniform_groups, get_multi_bit_tuniform_groups};
use benchmark::params_aliases::*;
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
use benchmark_spec::TestResult;
use rand::Rng;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
use tfhe::integer::U256;
use tfhe::keycache::NamedParam;
@@ -15,22 +14,10 @@ use tfhe::{
CompressedSquashedNoiseCiphertextList, ConfigBuilder, FheUint64,
};
fn write_result(file: &mut File, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
file.write_all(line.as_bytes()).expect(&error_message);
}
pub fn ct_sizes(results_file: &Path) {
let mut rng = rand::thread_rng();
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
let operator = OperatorType::Atomic;
@@ -87,7 +74,7 @@ pub fn ct_sizes(results_file: &Path) {
let params_record = param_fhe;
let mut write_and_record_result = |res: usize, test_name: &str, display_name: &str| {
write_result(&mut file, test_name, res);
benchmark_test_result.write_result(test_name, res);
write_to_json_unchecked::<u64, _>(
test_name,
params_record,
@@ -174,13 +161,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
let mut rng = rand::thread_rng();
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
let operator = OperatorType::Atomic;
@@ -205,7 +186,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
let cpk_size = bincode::serialize(&public_key).unwrap().len();
println!("PK size: {cpk_size} bytes");
write_result(&mut file, &test_name, cpk_size);
benchmark_test_result.write_result(&test_name, cpk_size);
write_to_json_unchecked::<u64, _>(
&test_name,
params,
@@ -227,7 +208,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
println!("Compact CT list for {NB_CTXT} CTs: {cctl_size} bytes");
write_result(&mut file, &test_name, cctl_size);
benchmark_test_result.write_result(&test_name, cctl_size);
write_to_json_unchecked::<u64, _>(
&test_name,
params,
@@ -273,7 +254,7 @@ pub fn cpk_and_cctl_sizes(results_file: &Path) {
println!("Compact CT list for {NB_CTXT} CTs: {cctl_size} bytes");
write_result(&mut file, &test_name, cctl_size);
benchmark_test_result.write_result(&test_name, cctl_size);
write_to_json_unchecked::<u64, _>(
&test_name,
params,

View File

@@ -1,8 +1,7 @@
use benchmark::params::get_classical_tuniform_groups;
use benchmark::params_aliases::*;
use benchmark::utilities::{write_to_json_unchecked, CryptoParametersRecord, OperatorType};
use std::fs::{File, OpenOptions};
use std::io::Write;
use benchmark_spec::TestResult;
use std::path::Path;
use tfhe::keycache::NamedParam;
use tfhe::shortint::atomic_pattern::compressed::CompressedAtomicPatternServerKey;
@@ -18,12 +17,6 @@ use tfhe::shortint::{
CompressedServerKey, PBSParameters, ServerKey,
};
fn write_result(file: &mut File, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
file.write_all(line.as_bytes()).expect(&error_message);
}
fn client_server_key_sizes(results_file: &Path) {
let shortint_params_vec: Vec<PBSParameters> = vec![
BENCH_PARAM_MESSAGE_1_CARRY_1_KS_PBS_TUNIFORM_2M128.into(),
@@ -59,11 +52,8 @@ fn client_server_key_sizes(results_file: &Path) {
BENCH_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_3_CARRY_3_KS_PBS_TUNIFORM_2M128.into(),
BENCH_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_4_CARRY_4_KS_PBS_TUNIFORM_2M128.into(),
];
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
let operator = OperatorType::Atomic;
@@ -83,7 +73,8 @@ fn client_server_key_sizes(results_file: &Path) {
let ksk_size = sks.key_switching_key_size_bytes();
let test_name = format!("shortint_key_sizes_{}_ksk", params.name());
write_result(&mut file, &test_name, ksk_size);
benchmark_test_result.write_result(&test_name, ksk_size);
write_to_json_unchecked::<u64, _>(
&test_name,
params,
@@ -103,7 +94,8 @@ fn client_server_key_sizes(results_file: &Path) {
let bsk_size = sks.bootstrapping_key_size_bytes();
let test_name = format!("shortint_key_sizes_{}_bsk", params.name());
write_result(&mut file, &test_name, bsk_size);
benchmark_test_result.write_result(&test_name, bsk_size);
write_to_json_unchecked::<u64, _>(
&test_name,
params,
@@ -124,7 +116,8 @@ fn client_server_key_sizes(results_file: &Path) {
let bsk_compressed_size = sks_compressed.bootstrapping_key_size_bytes();
let test_name = format!("shortint_key_sizes_{}_bsk_compressed", params.name());
write_result(&mut file, &test_name, bsk_compressed_size);
benchmark_test_result.write_result(&test_name, bsk_compressed_size);
write_to_json_unchecked::<u64, _>(
&test_name,
params,
@@ -152,12 +145,12 @@ fn measure_serialized_size<T: serde::Serialize, P: Into<CryptoParametersRecord<u
param_name: &str,
test_name_suffix: &str,
display_name: &str,
file: &mut File,
file: &mut TestResult,
) {
let serialized = bincode::serialize(to_serialize).unwrap();
let size = serialized.len();
let test_name = format!("shortint_key_sizes_{param_name}_{test_name_suffix}");
write_result(file, &test_name, size);
file.write_result(&test_name, size);
write_to_json_unchecked::<u64, _>(
&test_name,
param.clone(),
@@ -172,11 +165,7 @@ fn measure_serialized_size<T: serde::Serialize, P: Into<CryptoParametersRecord<u
}
fn tuniform_key_set_sizes(results_file: &Path) {
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
println!("Measuring shortint key sizes:");
@@ -200,7 +189,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"ksk",
"KSK",
&mut file,
&mut benchmark_test_result,
);
measure_serialized_size(
&ap.bootstrapping_key,
@@ -208,7 +197,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"bsk",
"BSK",
&mut file,
&mut benchmark_test_result,
);
}
AtomicPatternServerKey::KeySwitch32(ap) => {
@@ -218,7 +207,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"ksk",
"KSK",
&mut file,
&mut benchmark_test_result,
);
measure_serialized_size(
&ap.bootstrapping_key,
@@ -226,7 +215,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"bsk",
"BSK",
&mut file,
&mut benchmark_test_result,
);
}
AtomicPatternServerKey::Dynamic(_) => panic!("Dynamic atomic pattern not supported"),
@@ -240,7 +229,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"ksk_compressed",
"KSK",
&mut file,
&mut benchmark_test_result,
);
measure_serialized_size(
&comp_ap.bootstrapping_key(),
@@ -248,7 +237,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"bsk_compressed",
"BSK",
&mut file,
&mut benchmark_test_result,
);
}
CompressedAtomicPatternServerKey::KeySwitch32(comp_ap) => {
@@ -258,7 +247,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"ksk_compressed",
"KSK",
&mut file,
&mut benchmark_test_result,
);
measure_serialized_size(
&comp_ap.bootstrapping_key(),
@@ -266,7 +255,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_fhe_name,
"bsk_compressed",
"BSK",
&mut file,
&mut benchmark_test_result,
);
}
}
@@ -278,14 +267,21 @@ fn tuniform_key_set_sizes(results_file: &Path) {
let compressed_pk = CompressedCompactPublicKey::new(&compact_private_key);
let pk = compressed_pk.decompress();
measure_serialized_size(&pk, pke_param, &param_pke_name, "cpk", "CPK", &mut file);
measure_serialized_size(
&pk,
pke_param,
&param_pke_name,
"cpk",
"CPK",
&mut benchmark_test_result,
);
measure_serialized_size(
&compressed_pk,
pke_param,
&param_pke_name,
"cpk_compressed",
"CPK",
&mut file,
&mut benchmark_test_result,
);
let casting_param = dedicated_pke_params.ksk_params;
@@ -303,7 +299,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_casting_name,
"casting_key",
"CastKey",
&mut file,
&mut benchmark_test_result,
);
measure_serialized_size(
&compressed_casting_key.into_raw_parts().0,
@@ -311,7 +307,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_casting_name,
"casting_key_compressed",
"CastKey",
&mut file,
&mut benchmark_test_result,
);
}
@@ -329,7 +325,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_compression_name,
"compression_key",
"CompressionKey",
&mut file,
&mut benchmark_test_result,
);
measure_serialized_size(
&decompression_key,
@@ -337,7 +333,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_compression_name,
"decompression_key",
"CompressionKey",
&mut file,
&mut benchmark_test_result,
);
let (compressed_compression_key, compressed_decompression_key) =
@@ -349,7 +345,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_compression_name,
"compressed_compression_key",
"CompressedCompressionKey",
&mut file,
&mut benchmark_test_result,
);
measure_serialized_size(
&compressed_decompression_key,
@@ -357,7 +353,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&param_compression_name,
"compressed_decompression_key",
"CompressedCompressionKey",
&mut file,
&mut benchmark_test_result,
);
}
@@ -373,7 +369,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&noise_squashing_param.name(),
"noise_squashing_key",
"NoiseSquashingKey",
&mut file,
&mut benchmark_test_result,
);
if let Some(noise_squashing_comp_param) =
meta_noise_squashing_param.compression_parameters
@@ -392,7 +388,7 @@ fn tuniform_key_set_sizes(results_file: &Path) {
&noise_squashing_comp_param.name(),
"noise_squashing_compression_key",
"NoiseSquashingCompressionKey",
&mut file,
&mut benchmark_test_result,
);
}
}

View File

@@ -1,9 +1,8 @@
use benchmark::utilities::{write_to_json_unchecked, OperatorType};
use benchmark_spec::TestResult;
use clap::Parser;
use std::collections::HashMap;
use std::fs;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
use tfhe::keycache::NamedParam;
use tfhe::shortint::keycache::get_shortint_parameter_set_from_name;
@@ -29,18 +28,8 @@ fn params_from_name(name: &str) -> ClassicPBSParameters {
}
}
fn write_result(file: &mut File, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
file.write_all(line.as_bytes()).expect(&error_message);
}
pub fn parse_wasm_benchmarks(results_file: &Path, raw_results_file: &Path) {
File::create(results_file).expect("create results file failed");
let mut file = OpenOptions::new()
.append(true)
.open(results_file)
.expect("cannot open parsed results file");
let mut benchmark_test_result = TestResult::from_path(results_file);
let operator = OperatorType::Atomic;
@@ -60,10 +49,10 @@ pub fn parse_wasm_benchmarks(results_file: &Path, raw_results_file: &Path) {
let params: PBSParameters = params_from_name(name_parts[1]).into();
println!("{name_parts:?}");
if full_name.contains("_size") {
write_result(&mut file, &prefixed_full_name, *val as usize);
benchmark_test_result.write_result(&prefixed_full_name, *val as usize);
} else {
let value_in_ns = (val * 1_000_000_f32) as usize;
write_result(&mut file, &prefixed_full_name, value_in_ns);
benchmark_test_result.write_result(&prefixed_full_name, value_in_ns);
}
write_to_json_unchecked::<u64, _>(

View File

@@ -342,28 +342,6 @@ impl<G: Curve> Proof<G> {
None => ComputeLoad::Verify,
}
}
pub fn to_le_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
let Self {
c_hat,
c_y,
pi,
compute_load_proof_fields,
} = self;
bytes.extend_from_slice(c_hat.to_le_bytes().as_ref());
bytes.extend_from_slice(c_y.to_le_bytes().as_ref());
bytes.extend_from_slice(pi.to_le_bytes().as_ref());
let (c_hat_t_bytes, c_h_bytes, pi_kzg_bytes) =
ComputeLoadProofFields::to_le_bytes(compute_load_proof_fields);
bytes.extend_from_slice(&c_hat_t_bytes);
bytes.extend_from_slice(&c_h_bytes);
bytes.extend_from_slice(&pi_kzg_bytes);
bytes
}
}
impl<G: Curve> ParameterSetConformant for Proof<G> {
@@ -426,26 +404,6 @@ pub(crate) struct ComputeLoadProofFields<G: Curve> {
pub(crate) pi_kzg: G::G1,
}
impl<G: Curve> ComputeLoadProofFields<G> {
#[allow(clippy::type_complexity)]
fn to_le_bytes(fields: &Option<Self>) -> (Box<[u8]>, Box<[u8]>, Box<[u8]>) {
if let Some(ComputeLoadProofFields {
c_hat_t,
c_h,
pi_kzg,
}) = fields.as_ref()
{
(
Box::from(G::G2::to_le_bytes(*c_hat_t).as_ref()),
Box::from(G::G1::to_le_bytes(*c_h).as_ref()),
Box::from(G::G1::to_le_bytes(*pi_kzg).as_ref()),
)
} else {
(Box::from([]), Box::from([]), Box::from([]))
}
}
}
type CompressedG2<G> = <<G as Curve>::G2 as Compressible>::Compressed;
type CompressedG1<G> = <<G as Curve>::G1 as Compressible>::Compressed;

View File

@@ -440,44 +440,6 @@ impl<G: Curve> Proof<G> {
pub fn hash_config(&self) -> PkeV2SupportedHashConfig {
self.hash_config
}
pub fn to_le_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
let Self {
C_hat_e,
C_e,
C_r_tilde,
C_R,
C_hat_bin,
C_y,
C_h1,
C_h2,
C_hat_t,
pi,
pi_kzg,
compute_load_proof_fields,
hash_config: _,
} = self;
bytes.extend_from_slice(C_hat_e.to_le_bytes().as_ref());
bytes.extend_from_slice(C_e.to_le_bytes().as_ref());
bytes.extend_from_slice(C_r_tilde.to_le_bytes().as_ref());
bytes.extend_from_slice(C_R.to_le_bytes().as_ref());
bytes.extend_from_slice(C_hat_bin.to_le_bytes().as_ref());
bytes.extend_from_slice(C_y.to_le_bytes().as_ref());
bytes.extend_from_slice(C_h1.to_le_bytes().as_ref());
bytes.extend_from_slice(C_h2.to_le_bytes().as_ref());
bytes.extend_from_slice(C_hat_t.to_le_bytes().as_ref());
bytes.extend_from_slice(pi.to_le_bytes().as_ref());
bytes.extend_from_slice(pi_kzg.to_le_bytes().as_ref());
let (C_hat_h3_bytes, C_hat_w_bytes) =
ComputeLoadProofFields::to_le_bytes(compute_load_proof_fields);
bytes.extend_from_slice(&C_hat_h3_bytes);
bytes.extend_from_slice(&C_hat_w_bytes);
bytes
}
}
/// These fields can be pre-computed on the prover side in the faster Verifier scheme. If that's the

View File

@@ -99,7 +99,7 @@ serde-wasm-bindgen = { workspace = true, optional = true }
getrandom = { workspace = true, optional = true }
bytemuck = { workspace = true }
tfhe-hpu-backend = { version = "0.5", path = "../backends/tfhe-hpu-backend", optional = true }
tfhe-hpu-backend = { version = "0.4", path = "../backends/tfhe-hpu-backend", optional = true }
[features]
default = ["avx512"]

View File

@@ -8,23 +8,23 @@
<rect x="0" y="40" width="300" height="520" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="520" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Negation (-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">77.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">71.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">9.08 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">8.4 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Add / Sub (+,-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">91.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">93.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">9.07 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">8.35 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Mul (x)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">357 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">352 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">32.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">122 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Equal / Not Equal (eq, ne)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="180.0">72.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="180.0">70.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">7.03 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="180.0">6.77 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Comparisons (ge, gt, le, lt)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="220.0">89.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="220.0">87.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">10.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="220.0">6.81 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Max / Min (max, min)</text>
@@ -32,31 +32,31 @@
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">15.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="260.0">11.7 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Bitwise operations (&amp;, |, ^)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="300.0">19.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="300.0">19.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">1.99 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="300.0">2.95 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Div / Rem (/, %)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="340.0">4.88 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="340.0">5.04 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">514 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="340.0">912 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (&lt;&lt;, &gt;&gt;)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="380.0">121 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="380.0">119 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">18.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="380.0">25.8 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="420.0">121 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="420.0">119 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">18.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="420.0">27.9 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="460.0">222 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="460.0">223 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">20.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="460.0">14.7 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="500.0">246 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="500.0">244 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">21.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="500.0">14.8 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="540.0">Select</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="540.0">40.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="540.0">39.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">4.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="540.0">5.53 ms</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -7,13 +7,13 @@
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">whitepaper</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="60.0">253 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="60.0">25.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="60.0">276 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="60.0">23.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">no_cmux</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="100.0">256 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="100.0">25.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="100.0">238 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="100.0">24.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">overflow</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="140.0">238 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="405.0" y="140.0">225 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="615.0" y="140.0">21.3 ops/s</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -15,83 +15,83 @@
<rect x="0" y="40" width="300" height="520" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="520" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Negation (-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">50.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">55.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">57.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">77.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">96.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">52.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">55.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">54.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">76.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">96.0 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Add / Sub (+,-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">50.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">55.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">74.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">91.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">150 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">50.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">55.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">75.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">96.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">145 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Mul (x)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">89.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">89.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">131 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">195 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">357 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.02 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">363 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.01 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Equal / Not Equal (eq, ne)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">33.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">52.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">52.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">72.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">72.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">33.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">50.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">51.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">71.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">72.0 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Comparisons (ge, gt, le, lt)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">32.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">52.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">70.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">89.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">34.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">50.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">70.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">88.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">128 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Max / Min (max, min)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">69.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">88.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">70.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">88.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">109 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">128 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">173 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">131 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">168 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Bitwise operations (&amp;, |, ^)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">17.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">18.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">19.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">19.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">19.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">17.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">18.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">18.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">18.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">20.2 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Div / Rem (/, %)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">460 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">1.01 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">2.22 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">4.88 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">12.6 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">457 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">1.0 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">2.2 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">4.99 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">12.5 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (&lt;&lt;, &gt;&gt;)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">53.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">74.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">97.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">121 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">158 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">54.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">75.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">97.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">122 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">150 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">54.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">75.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">94.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">121 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">165 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">53.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">75.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">96.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">116 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">164 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">88.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">148 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">169 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">222 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">275 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">86.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">140 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">164 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">220 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">264 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">110 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">163 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">186 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">246 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">290 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">103 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">159 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">183 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">236 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">279 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="540.0">Select</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">36.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">36.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">38.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">40.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">43.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">35.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">37.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">36.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">39.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">42.0 ms</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -15,65 +15,65 @@
<rect x="0" y="40" width="300" height="400" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="400" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Add / Sub (+,-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">53.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">55.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">57.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">78.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">99.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">50.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">54.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">54.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">76.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">95.2 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Mul (x)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">71.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">70.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">115 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">155 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">207 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">422 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">156 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">208 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">412 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Equal / Not Equal (eq, ne)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">34.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">33.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">52.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">52.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">72.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">33.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">33.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">52.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">53.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">71.2 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Comparisons (ge, gt, le, lt)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">38.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">34.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">54.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">31.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">34.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">51.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">70.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">90.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">90.1 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Max / Min (max, min)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">54.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">53.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">71.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">91.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">110 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">52.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">52.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">71.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">91.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">108 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Bitwise operations (&amp;, |, ^)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">17.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">17.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">18.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">19.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">19.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">19.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">19.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">20.7 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Div (/)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">136 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">172 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">245 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">437 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">792 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">126 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">182 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">234 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">427 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">799 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Rem (%)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">235 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">337 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">468 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">690 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.27 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">244 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">334 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">462 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">657 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.19 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (&lt;&lt;, &gt;&gt;)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">17.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">18.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">19.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">19.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">21.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">17.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">18.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">19.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">19.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">19.8 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">18.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">18.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">19.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">19.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">20.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">17.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">18.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">18.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">20.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">21.0 ms</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -15,83 +15,83 @@
<rect x="0" y="40" width="300" height="520" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="520" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Negation (-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">804 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">372 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">181 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">86.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">42.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">824 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">388 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">184 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">88.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">42.8 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Add / Sub (+,-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">733 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">356 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">167 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">82.6 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">40.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">752 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">368 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">172 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">82.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">39.5 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Mul (x)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">293 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">71.9 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">18.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">4.58 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.19 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">283 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">65.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">17.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">4.68 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">1.17 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Equal / Not Equal (eq, ne)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">1.6 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">740 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">392 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">200 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">101 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">1.65 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">748 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">391 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">195 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">102 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Comparisons (ge, gt, le, lt)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.58 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">733 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">354 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">171 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">64.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.62 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">745 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">355 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">170 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">65.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Max / Min (max, min)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">493 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">236 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">116 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">58.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">25.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">488 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">239 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">117 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">57.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">25.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Bitwise operations (&amp;, |, ^)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">2.1 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">981 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">490 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">262 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">130 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">2.14 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">1.06 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">537 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">270 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">136 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Div / Rem (/, %)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">45.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">12.9 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">3.56 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">0.893 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">0.223 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">42.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">12.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">3.51 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">0.914 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">0.143 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (&lt;&lt;, &gt;&gt;)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">464 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">183 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">76.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">32.4 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">14.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">469 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">182 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">74.5 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">32.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">14.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">391 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">397 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">170 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">74.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">32.5 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">72.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">32.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">14.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">625 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">247 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">108 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">44.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">19.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">621 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">235 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">104 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">41.8 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">17.8 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">542 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">220 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">102 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">42.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">18.6 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">536 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">207 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="500.0">96.4 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="500.0">40.4 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="500.0">17.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="540.0">Select</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">676 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">350 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">176 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">84.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">42.6 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="540.0">699 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="540.0">351 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="540.0">175 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="540.0">87.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="540.0">43.4 ops/s</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -15,65 +15,65 @@
<rect x="0" y="40" width="300" height="400" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="400" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">Add / Sub (+,-)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">810 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">379 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">178 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">86.0 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">41.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="60.0">836 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="60.0">383 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">184 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="60.0">87.9 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="60.0">42.5 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">Mul (x)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">658 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">185 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">57.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">17.6 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">4.83 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="100.0">659 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="100.0">182 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">52.8 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="100.0">16.5 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="100.0">4.79 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">Equal / Not Equal (eq, ne)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">2.69 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">1.57 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">723 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">378 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">192 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="140.0">2.73 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="140.0">1.68 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">757 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="140.0">399 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="140.0">198 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">Comparisons (ge, gt, le, lt)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">2.61 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">1.63 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">717 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">348 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">172 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="180.0">2.82 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="180.0">1.64 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="180.0">747 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="180.0">356 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="180.0">173 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="220.0">Max / Min (max, min)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.15 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">621 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">302 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">148 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">73.6 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="220.0">1.18 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="220.0">645 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="220.0">305 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="220.0">150 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="220.0">73.2 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="260.0">Bitwise operations (&amp;, |, ^)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">2.11 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">1.04 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">516 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">260 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">128 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="260.0">2.31 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="260.0">1.12 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="260.0">555 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="260.0">276 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="260.0">139 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="300.0">Div (/)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">203 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">73.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">24.8 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">7.38 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">2.16 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="300.0">196 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="300.0">69.6 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="300.0">23.7 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="300.0">7.63 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="300.0">2.13 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="340.0">Rem (%)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">130 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">49.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">17.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">5.65 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.75 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="340.0">114 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="340.0">44.5 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="340.0">16.6 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="340.0">5.78 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="340.0">1.66 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="380.0">Left / Right Shifts (&lt;&lt;, &gt;&gt;)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">2.01 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">1.02 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">510 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">247 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">124 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="380.0">2.13 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="380.0">1.07 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="380.0">546 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="380.0">270 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="380.0">138 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="420.0">Left / Right Rotations (left_rotate, right_rotate)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">2.01 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">992 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">517 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">254 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">124 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="420.0">2.14 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="420.0">1.07 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="420.0">541 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">270 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">137 ops/s</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -9,25 +9,25 @@
<rect x="0" y="40" width="300" height="160" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="160" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">9.57 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="60.0">12.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">112 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">1.58 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">9.54 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="60.0">12.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">111 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">1.39 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">MB-PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.42 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.71 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">30.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">257 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.02 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.55 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">30.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">244 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">KS - PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">11.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">15.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">126 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">1.58 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">10.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">15.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">125 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">1.51 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">KS - MB-PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">6.67 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">8.49 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">46.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">388 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">5.56 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">7.29 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">61.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">418 ms</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -9,25 +9,25 @@
<rect x="0" y="40" width="300" height="160" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="160" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">8.93 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="60.0">8.94 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="60.0">11.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">102 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">654 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="60.0">104 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="60.0">670 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">MB-PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.58 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">28.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">214 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="100.0">4.87 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="100.0">4.53 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="100.0">30.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="100.0">185 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">KS - PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">10.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">14.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">119 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">865 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="140.0">10.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="140.0">15.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="140.0">120 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="140.0">871 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="180.0">KS - MB-PBS</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">6.96 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">7.59 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">47.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">247 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="352.5" y="180.0">6.83 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="457.5" y="180.0">7.13 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="562.5" y="180.0">44.7 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="667.5" y="180.0">228 ms</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -6,11 +6,11 @@
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.53 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.66 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.55 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.66 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.76 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.8 s</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -8,17 +8,17 @@
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">209 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">43.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">67.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">276 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">44.0 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">66.0 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">211 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">277 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">44.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">72.9 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">70.3 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">219 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">293 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">49.1 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">185 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">184 ms</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -8,17 +8,17 @@
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">8.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">265 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">129 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">7.9 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">274 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">131 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">8.36 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">259 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">50.8 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">7.9 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">277 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">51.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">8.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">236 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.38 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">7.73 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">242 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.62 ops/s</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -6,11 +6,11 @@
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.71 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">1.94 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.72 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">1.96 s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.93 s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">2.13 s</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -8,17 +8,17 @@
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">214 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">31.2 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">52.5 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">292 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">31.4 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">51.8 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">217 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">31.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">57.3 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">294 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">31.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">56.2 ms</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">225 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">33.6 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">170 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">317 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">33.8 ms</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">167 ms</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -8,17 +8,17 @@
<rect x="0" y="40" width="300" height="120" fill="#fbbc04"/>
<rect x="300" y="40" width="420" height="120" fill="#f3f3f3"/>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="60.0">1xFheUint64 (64 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">7.78 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">877 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">200 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="60.0">7.3 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="60.0">988 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="60.0">201 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="100.0">4xFheUint64 (256 bits) </text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">7.79 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">931 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">58.9 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="100.0">7.23 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="100.0">987 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="100.0">59.5 ops/s</text>
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="140.0">32xFheUint64 (2048 bits)</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">7.77 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">993 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.59 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="370.0" y="140.0">7.1 ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="140.0">1.11 k.ops/s</text>
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="650.0" y="140.0">8.85 ops/s</text>
<line stroke="white" stroke-width="2" x1="0" y1="0" x2="720" y2="0"/>
<line stroke="white" stroke-width="2" x1="0" y1="40" x2="720" y2="40"/>
<line stroke="white" stroke-width="2" x1="0" y1="80" x2="720" y2="80"/>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -97,76 +97,6 @@ pub fn main() {
}
```
## Example: Re-randomization of a `ProvenCompactCiphertextList`
Untrusted user inputs received in a `ProvenCompactCiphertextList` should also be re-randomized.
Here is how to do it:
```rust
use tfhe::prelude::*;
use tfhe::shortint::parameters::v1_6::meta::cpu::V1_6_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128;
use tfhe::zk::{CompactPkeCrs, ZkComputeLoad};
use tfhe::{
CompactPublicKey, Config, FheBool, FheInt8, FheUint64, ProvenCompactCiphertextList,
ReRandomizationContext, generate_keys, set_server_key,
};
pub fn main() {
let config = Config::from(V1_6_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128);
let (cks, sks) = generate_keys(config);
let cpk = CompactPublicKey::new(&cks);
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
let rerand_domain_separator = *b"TFHE_Rrd";
let crs = CompactPkeCrs::from_config(config, 2048).unwrap();
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
set_server_key(sks);
// Generate a list of ciphertexts
let clear_a = rand::random::<u64>();
let clear_b = rand::random::<i8>();
let compact_list = ProvenCompactCiphertextList::builder(&cpk)
.push(clear_a)
.push(clear_b)
.push(false)
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
.unwrap();
// Simulate a 256 bits nonce
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
let mut re_rand_context = ReRandomizationContext::new(
rerand_domain_separator,
[b"expand".as_slice(), nonce.as_slice()],
compact_public_encryption_domain_separator,
);
// Add the compact list to the context
re_rand_context.add_ciphertext(&compact_list);
let mut seed_gen = re_rand_context.finalize();
// Verify, re_randomize and expand
let expander = compact_list
.verify_re_randomize_and_expand(&crs, &cpk, &metadata, seed_gen.next_seed().unwrap())
.unwrap();
let a: FheUint64 = expander.get(0).unwrap().unwrap();
let b: FheInt8 = expander.get(1).unwrap().unwrap();
let c: FheBool = expander.get(2).unwrap().unwrap();
let dec_a: u64 = a.decrypt(&cks);
assert_eq!(dec_a, clear_a);
let dec_b: i8 = b.decrypt(&cks);
assert_eq!(dec_b, clear_b);
let dec_c: bool = c.decrypt(&cks);
assert!(!dec_c);
}
```
## Managing legacy Re-Randomization API
Because of an API change in version 1.6 you may find yourself needing to manage older keys using the old API, the following example shows how it can be done:

View File

@@ -92,7 +92,6 @@ pub fn glwe_ciphertext_add_assign<Scalar, LhsCont, RhsCont>(
lhs.ciphertext_modulus(),
rhs.ciphertext_modulus()
);
assert!(lhs.ciphertext_modulus().is_power_of_two());
slice_wrapping_add_assign(lhs.as_mut(), rhs.as_ref());
}
@@ -197,7 +196,6 @@ pub fn glwe_ciphertext_add<Scalar, OutputCont, LhsCont, RhsCont>(
output.ciphertext_modulus(),
rhs.ciphertext_modulus()
);
assert!(lhs.ciphertext_modulus().is_power_of_two());
slice_wrapping_add(output.as_mut(), lhs.as_ref(), rhs.as_ref());
}
@@ -642,7 +640,6 @@ where
Scalar: UnsignedInteger,
InCont: ContainerMut<Element = Scalar>,
{
assert!(ct.ciphertext_modulus().is_power_of_two());
slice_wrapping_opposite_assign(ct.as_mut());
}
@@ -726,8 +723,6 @@ pub fn glwe_ciphertext_cleartext_mul_assign<Scalar, InCont>(
Scalar: UnsignedInteger,
InCont: ContainerMut<Element = Scalar>,
{
assert!(lhs.ciphertext_modulus().is_power_of_two());
slice_wrapping_scalar_mul_assign(lhs.as_mut(), rhs.0);
}
@@ -913,7 +908,6 @@ pub fn glwe_ciphertext_sub_assign<Scalar, LhsCont, RhsCont>(
lhs.ciphertext_modulus(),
rhs.ciphertext_modulus()
);
assert!(lhs.ciphertext_modulus().is_power_of_two());
slice_wrapping_sub_assign(lhs.as_mut(), rhs.as_ref());
}

View File

@@ -816,111 +816,6 @@ pub fn lwe_ciphertext_sub<Scalar, OutputCont, LhsCont, RhsCont>(
lwe_ciphertext_sub_assign(output, rhs);
}
/// Add the right-hand side [`LWE compact ciphertext list`](`LweCompactCiphertextList`) to the
/// left-hand side [`LWE compact ciphertext list`](`LweCompactCiphertextList`) updating it in-place.
///
/// # Example
///
/// ```rust
/// use tfhe::core_crypto::prelude::*;
///
/// // DISCLAIMER: these toy example parameters are not guaranteed to be secure or yield correct
/// // computations
/// // Define parameters for LweCompactCiphertextList creation
/// let lwe_dimension = LweDimension(2048);
/// let lwe_ciphertext_count = LweCiphertextCount(3);
/// let noise_distribution =
/// Gaussian::from_dispersion_parameter(StandardDev(0.00000000000000029403601535432533), 0.0);
/// let ciphertext_modulus = CiphertextModulus::new_native();
///
/// // Create the PRNG
/// let mut seeder = new_seeder();
/// let seeder = seeder.as_mut();
/// let mut secret_generator = SecretRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed());
/// let mut encryption_generator =
/// EncryptionRandomGenerator::<DefaultRandomGenerator>::new(seeder.seed(), seeder);
///
/// // Create the LweSecretKey
/// let lwe_secret_key =
/// allocate_and_generate_new_binary_lwe_secret_key(lwe_dimension, &mut secret_generator);
///
/// let lwe_compact_public_key = allocate_and_generate_new_lwe_compact_public_key(
/// &lwe_secret_key,
/// noise_distribution,
/// ciphertext_modulus,
/// &mut encryption_generator,
/// );
///
/// // Create the plaintext
/// let msg = 3u64;
/// let encoded_msg = msg << 60;
/// let input_plaintext_list =
/// PlaintextList::new(encoded_msg, PlaintextCount(lwe_ciphertext_count.0));
///
/// // Create and encrypt a new LweCompactCiphertextList
/// let mut lwe_compact_ct_list = LweCompactCiphertextList::new(
/// 0u64,
/// lwe_dimension.to_lwe_size(),
/// lwe_ciphertext_count,
/// ciphertext_modulus,
/// );
/// encrypt_lwe_compact_ciphertext_list_with_compact_public_key(
/// &lwe_compact_public_key,
/// &mut lwe_compact_ct_list,
/// &input_plaintext_list,
/// noise_distribution,
/// noise_distribution,
/// encryption_generator.noise_generator_mut(),
/// );
///
/// let rhs = lwe_compact_ct_list.clone();
///
/// lwe_compact_ciphertext_list_add_assign(&mut lwe_compact_ct_list, &rhs);
///
/// // Expand and decrypt
/// let lwe_ciphertext_list = lwe_compact_ct_list.expand_into_lwe_ciphertext_list();
///
/// let mut output_plaintext_list =
/// PlaintextList::new(0u64, PlaintextCount(lwe_ciphertext_count.0));
///
/// decrypt_lwe_ciphertext_list(
/// &lwe_secret_key,
/// &lwe_ciphertext_list,
/// &mut output_plaintext_list,
/// );
///
/// // Round and remove encoding
/// // First create a decomposer working on the high 4 bits corresponding to our encoding.
/// let decomposer = SignedDecomposer::new(DecompositionBaseLog(4), DecompositionLevelCount(1));
///
/// // Round and remove encoding in the output plaintext list
/// output_plaintext_list
/// .iter_mut()
/// .for_each(|x| *x.0 = decomposer.closest_representable(*x.0) >> 60);
///
/// // Check we recovered the expected result
/// assert!(output_plaintext_list.iter().all(|x| *x.0 == msg + msg));
/// ```
pub fn lwe_compact_ciphertext_list_add_assign<Scalar, LhsCont, RhsCont>(
lhs: &mut LweCompactCiphertextList<LhsCont>,
rhs: &LweCompactCiphertextList<RhsCont>,
) where
Scalar: UnsignedInteger,
LhsCont: ContainerMut<Element = Scalar>,
RhsCont: Container<Element = Scalar>,
{
assert_eq!(
lhs.ciphertext_modulus(),
rhs.ciphertext_modulus(),
"Mismatched moduli between lhs ({:?}) and rhs ({:?}) LweCompactCiphertextList",
lhs.ciphertext_modulus(),
rhs.ciphertext_modulus()
);
assert!(lhs.ciphertext_modulus().is_power_of_two());
slice_wrapping_add_assign(lhs.as_mut(), rhs.as_ref());
}
// ============== Noise measurement trait implementations ============== //
use crate::core_crypto::commons::noise_formulas::noise_simulation::traits::{
LweUncorrelatedAdd, LweUncorrelatedSub, ScalarMul, ScalarMulAssign,

View File

@@ -13,7 +13,7 @@ pub(in crate::high_level_api) mod traits;
use crate::array::traits::TensorSlice;
use crate::high_level_api::array::traits::HasClear;
use crate::high_level_api::global_state;
use crate::high_level_api::integers::{FheIntId, FheIntegerType, FheUintId};
use crate::high_level_api::integers::{FheIntId, FheUintId};
use crate::high_level_api::keys::InternalServerKey;
use crate::high_level_api::re_randomization::ReRandomizationMetadata;
use crate::{FheBool, FheId, FheInt, FheUint, Tag};
@@ -24,8 +24,6 @@ pub use traits::{IOwnedArray, Slicing, SlicingMut};
use crate::array::stride::DynDimensions;
use crate::core_crypto::prelude::{Numeric, OverflowingAdd, SignedNumeric, UnsignedNumeric};
use crate::integer::block_decomposition::DecomposableInto;
#[cfg(feature = "gpu")]
use crate::integer::gpu::ciphertext::CudaIntegerRadixCiphertext;
use crate::integer::RadixCiphertext;
use crate::prelude::{CastFrom, CastInto};
pub use cpu::{
@@ -452,55 +450,6 @@ pub fn fhe_uint_array_contains_sub_slice<Id: FheUintId>(
})
}
pub fn fhe_array_contains<T>(data: &[T], value: &T) -> FheBool
where
T: FheIntegerType,
{
global_state::with_internal_keys(|sks| match sks {
InternalServerKey::Cpu(cpu_key) => {
let tmp_data = data
.iter()
.map(|element| element.on_cpu().into_owned())
.collect::<Vec<_>>();
let tmp_value = value.on_cpu();
let result = cpu_key
.pbs_key()
.contains_parallelized(&tmp_data, &*tmp_value);
FheBool::new(
result,
cpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(gpu_key) => {
use crate::high_level_api::details::MaybeCloned;
let streams = &gpu_key.streams;
let tmp_data = data
.iter()
.map(|element| match element.on_gpu(streams) {
MaybeCloned::Borrowed(ct) => ct.duplicate(streams),
MaybeCloned::Cloned(ct) => ct,
})
.collect::<Vec<_>>();
let tmp_value = value.on_gpu(streams);
let result = gpu_key.pbs_key().contains(&tmp_data, &*tmp_value, streams);
FheBool::new(
result,
gpu_key.tag.clone(),
ReRandomizationMetadata::default(),
)
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_) => {
panic!("HPU does not support contains() on FheIntegerType yet")
}
})
}
/// Small helper to reduce code
///
/// * num_bits: num bits of the FheType

View File

@@ -2,8 +2,6 @@ mod booleans;
mod signed;
mod unsigned;
use crate::high_level_api::array::fhe_array_contains;
use crate::high_level_api::integers::FheIntegerType;
use crate::{generate_keys, set_server_key, ClientKey, ConfigBuilder, FheId};
use rand::distributions::{Distribution, Standard};
use rand::random;
@@ -12,7 +10,7 @@ use std::fmt::Debug;
use crate::array::traits::IOwnedArray;
use crate::array::ClearArray;
use crate::high_level_api::array::{FheBackendArray, FheBackendArraySlice};
use crate::prelude::{FheDecrypt, FheEncrypt, FheTryEncrypt};
use crate::prelude::{FheDecrypt, FheTryEncrypt};
use std::ops::{BitAnd, BitOr, BitXor};
fn draw_random_values<T>(num_values: usize) -> Vec<T>
@@ -276,42 +274,3 @@ where
assert_eq!(result, expected_result);
}
}
fn test_case_contains<T, Clear>(ck: &ClientKey)
where
T: FheIntegerType + FheEncrypt<Clear, ClientKey>,
Standard: Distribution<Clear>,
Clear: Copy + Eq,
{
let values = draw_random_values::<Clear>(5);
// Pick one element that is guaranteed to be in the slice
let present_value = values[random::<usize>() % values.len()];
// Generate an absent value that is not in the slice
let absent_value = loop {
let candidate: Clear = random();
if !values.contains(&candidate) {
break candidate;
}
};
let data: Vec<T> = values.iter().map(|&v| T::encrypt(v, ck)).collect();
let present = T::encrypt(present_value, ck);
let result: bool = fhe_array_contains(&data, &present).decrypt(ck);
assert!(result);
let absent = T::encrypt(absent_value, ck);
let result: bool = fhe_array_contains(&data, &absent).decrypt(ck);
assert!(!result);
// Test with a duplicated value in the slice
let mut values_with_dup = values.clone();
values_with_dup.push(values[0]);
let data_with_dup: Vec<T> = values_with_dup.iter().map(|&v| T::encrypt(v, ck)).collect();
let present_dup = T::encrypt(values[0], ck);
let result: bool = fhe_array_contains(&data_with_dup, &present_dup).decrypt(ck);
assert!(result);
}

View File

@@ -101,21 +101,6 @@ fn test_cpu_dyn_bitand_scalar_slice() {
super::bitand_scalar_slice_test_case::<crate::FheUint32Array, u32>(&ck);
}
#[test]
fn test_contains() {
let ck = super::setup_default_cpu();
super::test_case_contains::<crate::FheUint8, u8>(&ck);
}
#[test]
#[cfg(feature = "gpu")]
fn test_contains_gpu() {
for setup_fn in crate::high_level_api::integers::unsigned::tests::gpu::GPU_SETUP_FN {
let ck = setup_fn();
super::test_case_contains::<crate::FheUint8, u8>(&ck);
}
}
#[test]
fn test_single_dimension() {
let config = ConfigBuilder::default().build();

View File

@@ -462,10 +462,7 @@ mod zk {
use crate::conformance::ParameterSetConformant;
use crate::high_level_api::global_state::device_of_internal_keys;
use crate::high_level_api::keys::InternalServerKey;
use crate::high_level_api::re_randomization::ReRandContextAdd;
use crate::integer::ciphertext::{
IntegerProvenCompactCiphertextListConformanceParams, ReRandomizationSeed,
};
use crate::integer::ciphertext::IntegerProvenCompactCiphertextListConformanceParams;
#[cfg(feature = "gpu")]
use crate::integer::gpu::zk::CudaProvenCompactCiphertextList;
use serde::Serializer;
@@ -623,13 +620,6 @@ mod zk {
const NAME: &'static str = "high_level_api::ProvenCompactCiphertextList";
}
impl ReRandContextAdd for ProvenCompactCiphertextList {
fn add_to_re_randomization_context(&self, context: &mut crate::ReRandomizationContext) {
let on_cpu = self.inner.on_cpu();
context.inner.add_proven_ciphertext_list(on_cpu)
}
}
impl ProvenCompactCiphertextList {
pub fn builder(pk: &CompactPublicKey) -> CompactCiphertextListBuilder {
CompactCiphertextListBuilder::new(pk)
@@ -665,7 +655,7 @@ mod zk {
pk: &CompactPublicKey,
metadata: &[u8],
) -> crate::Result<CompactCiphertextListExpander> {
self.maybe_verify_maybe_re_randomize_and_expand(Some((crs, pk, metadata)), None)
self.maybe_verify_and_expand(Some((crs, pk, metadata)))
}
#[doc(hidden)]
@@ -673,68 +663,27 @@ mod zk {
///
/// If you are here you were probably looking for it: use at your own risks.
pub fn expand_without_verification(&self) -> crate::Result<CompactCiphertextListExpander> {
self.maybe_verify_maybe_re_randomize_and_expand(None, None)
self.maybe_verify_and_expand(None)
}
pub fn verify_re_randomize_and_expand(
&self,
crs: &CompactPkeCrs,
pk: &CompactPublicKey,
metadata: &[u8],
seed: ReRandomizationSeed,
) -> crate::Result<CompactCiphertextListExpander> {
self.maybe_verify_maybe_re_randomize_and_expand(
Some((crs, pk, metadata)),
Some((pk, seed)),
)
}
#[doc(hidden)]
/// This function allows to re_randomize and expand a ciphertext without verifying the
/// associated proof.
///
/// If you are here you were probably looking for it: use at your own risks.
pub fn re_randomize_and_expand_without_verification(
&self,
pk: &CompactPublicKey,
seed: ReRandomizationSeed,
) -> crate::Result<CompactCiphertextListExpander> {
self.maybe_verify_maybe_re_randomize_and_expand(None, Some((pk, seed)))
}
/// Internal helper that does expansion, and optionally verification and re_randomization if
/// the required materials are provided
fn maybe_verify_maybe_re_randomize_and_expand(
/// Internal helper that does expansion, and verification only if crs, public key and
/// metadata are provided
fn maybe_verify_and_expand(
&self,
verification_materials: Option<(&CompactPkeCrs, &CompactPublicKey, &[u8])>,
re_randomization_materials: Option<(&CompactPublicKey, ReRandomizationSeed)>,
) -> crate::Result<CompactCiphertextListExpander> {
#[allow(irrefutable_let_patterns)]
if let InnerProvenCompactCiphertextList::Cpu(inner) = &self.inner {
// For WASM
if !inner.is_packed() && !inner.needs_casting() {
let expander = match (verification_materials, re_randomization_materials) {
(Some((crs, pk, metadata)), Some((_, seed))) => inner
.verify_re_randomize_and_expand(
crs,
&pk.key.key,
metadata,
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
seed,
),
(None, Some((pk, seed))) => inner
.re_randomize_and_expand_without_verification(
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
&pk.key.key,
seed,
),
(Some((crs, pk, metadata)), None) => inner.verify_and_expand(
let expander = match verification_materials {
Some((crs, pk, metadata)) => inner.verify_and_expand(
crs,
&pk.key.key,
metadata,
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
),
(None, None) => inner.expand_without_verification(
None => inner.expand_without_verification(
IntegerCompactCiphertextListExpansionMode::NoCastingAndNoUnpacking,
),
}?;
@@ -756,28 +705,14 @@ mod zk {
InnerProvenCompactCiphertextList::Cuda(inner) => &inner.h_proved_lists,
};
let expander = match (verification_materials, re_randomization_materials) {
(Some((crs, pk, metadata)), Some((_, seed))) => proven_ct
.verify_re_randomize_and_expand(
crs,
&pk.key.key,
metadata,
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
seed,
),
(Some((crs, pk, metadata)), None) => proven_ct.verify_and_expand(
let expander = match verification_materials {
Some((crs, pk, metadata)) => proven_ct.verify_and_expand(
crs,
&pk.key.key,
metadata,
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
),
(None, Some((pk, seed))) => proven_ct
.re_randomize_and_expand_without_verification(
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
&pk.key.key,
seed,
),
(None, None) => proven_ct.expand_without_verification(
None => proven_ct.expand_without_verification(
cpu_key.integer_compact_ciphertext_list_expansion_mode(),
),
}?;
@@ -799,28 +734,11 @@ mod zk {
};
let ksk = gpu_key.cpk_key_switching_key();
let expander = match (verification_materials, re_randomization_materials) {
(Some((crs, pk, metadata)), Some((_, seed))) => proven_ct
.verify_re_randomize_and_expand(
crs,
&pk.key.key,
metadata,
&ksk,
seed,
streams,
),
(Some((crs, pk, metadata)), None) => {
let expander = match verification_materials {
Some((crs, pk, metadata)) => {
proven_ct.verify_and_expand(crs, &pk.key.key, metadata, &ksk, streams)
}
(None, Some((pk, seed))) => proven_ct
.re_randomize_and_expand_without_verification(
&ksk,
&pk.key.key,
seed,
streams,
),
(None, None) => proven_ct.expand_without_verification(&ksk, streams),
None => proven_ct.expand_without_verification(&ksk, streams),
}?;
Ok(CompactCiphertextListExpander {

View File

@@ -58,9 +58,6 @@ pub(super) mod unsigned;
pub trait IntegerId: FheId + 'static {
type InnerCpu: crate::integer::IntegerRadixCiphertext;
#[cfg(feature = "gpu")]
type InnerGpu: crate::integer::gpu::ciphertext::CudaIntegerRadixCiphertext;
#[cfg(not(feature = "gpu"))]
type InnerGpu;
type InnerHpu;
@@ -92,23 +89,4 @@ pub trait FheIntegerType: Tagged + private::Sealed {
tag: Tag,
re_randomization_metadata: ReRandomizationMetadata,
) -> Self;
#[cfg(feature = "gpu")]
fn on_gpu(
&self,
streams: &crate::core_crypto::gpu::CudaStreams,
) -> MaybeCloned<'_, <Self::Id as IntegerId>::InnerGpu>;
#[cfg(feature = "gpu")]
fn into_gpu(
self,
streams: &crate::core_crypto::gpu::CudaStreams,
) -> <Self::Id as IntegerId>::InnerGpu;
#[cfg(feature = "gpu")]
fn from_gpu(
inner: <Self::Id as IntegerId>::InnerGpu,
tag: Tag,
re_randomization_metadata: ReRandomizationMetadata,
) -> Self;
}

View File

@@ -137,31 +137,6 @@ where
) -> Self {
Self::new(inner, tag, re_randomization_metadata)
}
#[cfg(feature = "gpu")]
fn on_gpu(
&self,
streams: &crate::core_crypto::gpu::CudaStreams,
) -> MaybeCloned<'_, <Self::Id as IntegerId>::InnerGpu> {
self.ciphertext.on_gpu(streams)
}
#[cfg(feature = "gpu")]
fn into_gpu(
self,
streams: &crate::core_crypto::gpu::CudaStreams,
) -> <Self::Id as IntegerId>::InnerGpu {
self.ciphertext.into_gpu(streams)
}
#[cfg(feature = "gpu")]
fn from_gpu(
inner: <Self::Id as IntegerId>::InnerGpu,
tag: Tag,
re_randomization_metadata: ReRandomizationMetadata,
) -> Self {
Self::new(inner, tag, re_randomization_metadata)
}
}
impl<Id> FheInt<Id>
@@ -235,30 +210,6 @@ where
self.ciphertext.current_device()
}
/// Returns an encrypted `true` if `value` is found in `cts`.
///
/// # Example
///
/// ```rust
/// use tfhe::prelude::*;
/// use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheInt16};
///
/// let (client_key, server_key) = generate_keys(ConfigBuilder::default());
/// set_server_key(server_key);
///
/// let a = FheInt16::encrypt(1i16, &client_key);
/// let b = FheInt16::encrypt(-2i16, &client_key);
/// let c = FheInt16::encrypt(3i16, &client_key);
/// let value = FheInt16::encrypt(-2i16, &client_key);
///
/// let result = FheInt16::contains(&[a, b, c], &value);
/// let decrypted = result.decrypt(&client_key);
/// assert!(decrypted);
/// ```
pub fn contains(cts: &[Self], value: &Self) -> FheBool {
crate::high_level_api::array::fhe_array_contains(cts, value)
}
/// Returns the absolute value
///
/// # Example

View File

@@ -1,54 +0,0 @@
use crate::high_level_api::integers::unsigned::fused_ops::impl_fused_mul_divs;
use crate::integer::bigint::{I1024, I2048, I256, I512};
// Standard types (always available)
//
// (NarrowFhe, WideFhe, NarrowScalar, WideScalar)
//
// Types without at least double-width FheInt (FheInt2048) are not supported.
impl_fused_mul_divs!(
(super::FheInt2, super::FheInt4, i8, i8),
(super::FheInt4, super::FheInt8, i8, i8),
(super::FheInt6, super::FheInt12, i8, i16),
(super::FheInt8, super::FheInt16, i8, i16),
(super::FheInt10, super::FheInt32, i16, i32),
(super::FheInt12, super::FheInt32, i16, i32),
(super::FheInt14, super::FheInt32, i16, i32),
(super::FheInt16, super::FheInt32, i16, i32),
(super::FheInt32, super::FheInt64, i32, i64),
(super::FheInt64, super::FheInt128, i64, i128),
(super::FheInt128, super::FheInt256, i128, I256),
(super::FheInt160, super::FheInt512, I256, I512),
(super::FheInt256, super::FheInt512, I256, I512),
(super::FheInt512, super::FheInt1024, I512, I1024),
(super::FheInt1024, super::FheInt2048, I1024, I2048),
);
#[cfg(feature = "extended-types")]
impl_fused_mul_divs!(
(super::FheInt24, super::FheInt48, i32, i64),
(super::FheInt40, super::FheInt80, i64, i128),
(super::FheInt48, super::FheInt96, i64, i128),
(super::FheInt56, super::FheInt112, i64, i128),
(super::FheInt72, super::FheInt144, i128, I256),
(super::FheInt80, super::FheInt160, i128, I256),
(super::FheInt88, super::FheInt176, i128, I256),
(super::FheInt96, super::FheInt192, i128, I256),
(super::FheInt104, super::FheInt208, i128, I256),
(super::FheInt112, super::FheInt224, i128, I256),
(super::FheInt120, super::FheInt240, i128, I256),
(super::FheInt136, super::FheInt512, I256, I512),
(super::FheInt144, super::FheInt512, I256, I512),
(super::FheInt152, super::FheInt512, I256, I512),
(super::FheInt168, super::FheInt512, I256, I512),
(super::FheInt176, super::FheInt512, I256, I512),
(super::FheInt184, super::FheInt512, I256, I512),
(super::FheInt192, super::FheInt512, I256, I512),
(super::FheInt200, super::FheInt512, I256, I512),
(super::FheInt208, super::FheInt512, I256, I512),
(super::FheInt216, super::FheInt512, I256, I512),
(super::FheInt224, super::FheInt512, I256, I512),
(super::FheInt232, super::FheInt512, I256, I512),
(super::FheInt240, super::FheInt512, I256, I512),
(super::FheInt248, super::FheInt512, I256, I512),
);

View File

@@ -3,7 +3,6 @@ mod compressed;
mod squashed_noise;
mod encrypt;
mod fused_ops;
mod inner;
mod ops;
mod overflowing_ops;

View File

@@ -253,9 +253,3 @@ fn test_safe_deserialize_conformant_compressed_fhe_int32() {
let decrypted: i32 = deserialized_a.decompress().decrypt(&client_key);
assert_eq!(decrypted, clear_a);
}
#[test]
fn test_int16_fused_mul_div() {
let client_key = setup_default_cpu();
super::test_case_int16_fused_mul_div(&client_key);
}

View File

@@ -373,11 +373,3 @@ fn test_gpu_get_div_size_on_gpu() {
check_valid_cuda_malloc_assert_oom(scalar_div_rem_tmp_buffer_size, GpuIndex::new(0));
}
}
#[test]
fn test_int16_fused_mul_div_gpu() {
for setup_fn in crate::high_level_api::integers::unsigned::tests::gpu::GPU_SETUP_FN {
let client_key = setup_fn();
super::test_case_int16_fused_mul_div(&client_key);
}
}

View File

@@ -519,71 +519,3 @@ fn test_case_min_max(cks: &ClientKey) {
assert_eq!(decrypted_min, a_val.min(b_val));
assert_eq!(decrypted_max, a_val.max(b_val));
}
fn test_case_int16_fused_mul_div(cks: &ClientKey) {
let mut rng = rand::thread_rng();
// Widening prevents incorrect result with signed values:
// (-200) * 200 = -40_000 which overflows i16 (min -32_768),
// but with widening: -40_000 / 100 = -400, correct.
{
let input = -200i16;
let mul = 200i16;
let div = 100i16;
let expected = -400i16;
let a = FheInt16::try_encrypt(input, cks).unwrap();
let b = FheInt16::try_encrypt(mul, cks).unwrap();
let result = (&a).fused_mul_scalar_div(&b, div);
let decrypted: i16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
let result = (&a).fused_scalar_mul_scalar_div(mul, div);
let decrypted: i16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
for _ in 0..5 {
let clear_a: i16 = rng.gen();
let clear_b: i16 = rng.gen();
let clear_c: i16 = loop {
let v: i16 = rng.gen();
if v != 0 {
break v;
}
};
let a = FheInt16::try_encrypt(clear_a, cks).unwrap();
let b = FheInt16::try_encrypt(clear_b, cks).unwrap();
let expected = (i32::from(clear_a) * i32::from(clear_b) / i32::from(clear_c)) as i16;
// encrypted * encrypted / scalar
{
let result = (&a).fused_mul_scalar_div(&b, clear_c);
let decrypted: i16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
// encrypted * scalar / scalar
{
let result = (&a).fused_scalar_mul_scalar_div(clear_b, clear_c);
let decrypted: i16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
// Owned variants
{
let result = a.fused_mul_scalar_div(b, clear_c);
let decrypted: i16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
// Need to encrypt again since "a" was consumed above
let a = FheInt16::try_encrypt(clear_a, cks).unwrap();
let result = a.fused_scalar_mul_scalar_div(clear_b, clear_c);
let decrypted: i16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
}
}

View File

@@ -174,31 +174,6 @@ where
) -> Self {
Self::new(inner, tag, re_randomization_metadata)
}
#[cfg(feature = "gpu")]
fn on_gpu(
&self,
streams: &crate::core_crypto::gpu::CudaStreams,
) -> MaybeCloned<'_, <Self::Id as IntegerId>::InnerGpu> {
self.ciphertext.on_gpu(streams)
}
#[cfg(feature = "gpu")]
fn into_gpu(
self,
streams: &crate::core_crypto::gpu::CudaStreams,
) -> <Self::Id as IntegerId>::InnerGpu {
self.ciphertext.into_gpu(streams)
}
#[cfg(feature = "gpu")]
fn from_gpu(
inner: <Self::Id as IntegerId>::InnerGpu,
tag: Tag,
re_randomization_metadata: ReRandomizationMetadata,
) -> Self {
Self::new(inner, tag, re_randomization_metadata)
}
}
impl<Id> Tagged for FheUint<Id>
@@ -562,30 +537,6 @@ where
collection.as_ref().iter().copied().sum()
}
/// Returns an encrypted `true` if `value` is found in `cts`.
///
/// # Example
///
/// ```rust
/// use tfhe::prelude::*;
/// use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheUint16};
///
/// let (client_key, server_key) = generate_keys(ConfigBuilder::default());
/// set_server_key(server_key);
///
/// let a = FheUint16::encrypt(1u16, &client_key);
/// let b = FheUint16::encrypt(2u16, &client_key);
/// let c = FheUint16::encrypt(3u16, &client_key);
/// let value = FheUint16::encrypt(2u16, &client_key);
///
/// let result = FheUint16::contains(&[a, b, c], &value);
/// let decrypted = result.decrypt(&client_key);
/// assert!(decrypted);
/// ```
pub fn contains(cts: &[Self], value: &Self) -> FheBool {
crate::high_level_api::array::fhe_array_contains(cts, value)
}
/// Returns the number of leading zeros in the binary representation of self.
///
/// # Example

View File

@@ -1,186 +0,0 @@
use crate::integer::bigint::{U1024, U2048, U256, U512};
/// Generates `FusedMulScalarDiv` impls for (encrypted * encrypted) / scalar.
///
/// Input tuple is of the form (NarrowFhe, WideFhe, NarrowScalar, WideScalar)`
/// Inputs are `NarrowFhe` and `NarrowScalar`, and get widened to `WideFhe` and `WideScalar`, mul
/// and div are computed on the widened values and result is truncated back down to `NarrowFhe`
macro_rules! impl_fused_mul_scalar_div {
($(
($fhe_narrow:ty, $fhe_wide:ty, $scalar_narrow:ty, $scalar_wide:ty)
),* $(,)?) => {
$(
// (&enc * &enc) / scalar (ref, ref, main impl)
impl crate::high_level_api::traits::FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow> for &$fhe_narrow {
type Output = $fhe_narrow;
fn fused_mul_scalar_div(
self,
mul: &$fhe_narrow,
div_scalar: $scalar_narrow,
) -> Self::Output {
use crate::core_crypto::prelude::CastFrom;
let wide_self = <$fhe_wide>::cast_from(self.clone());
let wide_mul = <$fhe_wide>::cast_from(mul.clone());
let wide_product = &wide_self * &wide_mul;
let wide_result = wide_product / <$scalar_wide>::cast_from(div_scalar);
<$fhe_narrow>::cast_from(wide_result)
}
}
// (enc * enc) / scalar (owned, owned)
impl crate::high_level_api::traits::FusedMulScalarDiv<$fhe_narrow, $scalar_narrow> for $fhe_narrow {
type Output = $fhe_narrow;
fn fused_mul_scalar_div(
self,
mul: $fhe_narrow,
div_scalar: $scalar_narrow,
) -> Self::Output {
use crate::high_level_api::traits::FusedMulScalarDiv;
<&Self as FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow>>::fused_mul_scalar_div(&self, &mul, div_scalar)
}
}
// (&enc * enc) / scalar (ref, owned)
impl crate::high_level_api::traits::FusedMulScalarDiv<$fhe_narrow, $scalar_narrow> for &$fhe_narrow {
type Output = $fhe_narrow;
fn fused_mul_scalar_div(
self,
mul: $fhe_narrow,
div_scalar: $scalar_narrow,
) -> Self::Output {
use crate::high_level_api::traits::FusedMulScalarDiv;
<Self as FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow>>::fused_mul_scalar_div(self, &mul, div_scalar)
}
}
// (enc * &enc) / scalar (owned, ref)
impl crate::high_level_api::traits::FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow> for $fhe_narrow {
type Output = $fhe_narrow;
fn fused_mul_scalar_div(
self,
mul: &$fhe_narrow,
div_scalar: $scalar_narrow,
) -> Self::Output {
use crate::high_level_api::traits::FusedMulScalarDiv;
<&Self as FusedMulScalarDiv<&$fhe_narrow, $scalar_narrow>>::fused_mul_scalar_div(&self, mul, div_scalar)
}
}
)*
};
}
pub(crate) use impl_fused_mul_scalar_div;
/// Generates `FusedScalarMulScalarDiv` impls for (encrypted * scalar) / scalar.
///
/// Input tuple is of the form (NarrowFhe, WideFhe, NarrowScalar, WideScalar)`
/// Inputs are `NarrowFhe` and `NarrowScalar`, and get widened to `WideFhe` and `WideScalar`, mul
/// and div are computed on the widened values and result is truncated back down to `NarrowFhe`
macro_rules! impl_fused_scalar_mul_scalar_div {
($(
($fhe_narrow:ty, $fhe_wide:ty, $scalar_narrow:ty, $scalar_wide:ty)
),* $(,)?) => {
$(
// (&enc * scalar) / scalar (ref, main impl)
impl crate::high_level_api::traits::FusedScalarMulScalarDiv<$scalar_narrow> for &$fhe_narrow {
type Output = $fhe_narrow;
fn fused_scalar_mul_scalar_div(
self,
mul_scalar: $scalar_narrow,
div_scalar: $scalar_narrow,
) -> Self::Output {
use crate::core_crypto::prelude::CastFrom;
let wide_self = <$fhe_wide>::cast_from(self.clone());
let wide_product = wide_self * <$scalar_wide>::cast_from(mul_scalar);
let wide_result = wide_product / <$scalar_wide>::cast_from(div_scalar);
<$fhe_narrow>::cast_from(wide_result)
}
}
// (enc * scalar) / scalar (owned)
impl crate::high_level_api::traits::FusedScalarMulScalarDiv<$scalar_narrow> for $fhe_narrow {
type Output = $fhe_narrow;
fn fused_scalar_mul_scalar_div(
self,
mul_scalar: $scalar_narrow,
div_scalar: $scalar_narrow,
) -> Self::Output {
use crate::high_level_api::traits::FusedScalarMulScalarDiv;
<&Self as FusedScalarMulScalarDiv<$scalar_narrow>>::fused_scalar_mul_scalar_div(&self, mul_scalar, div_scalar)
}
}
)*
};
}
pub(crate) use impl_fused_scalar_mul_scalar_div;
macro_rules! impl_fused_mul_divs {
($(
($fhe_narrow:ty, $fhe_wide:ty, $scalar_narrow:ty, $scalar_wide:ty)
),* $(,)?) => {
crate::high_level_api::integers::unsigned::fused_ops::impl_fused_mul_scalar_div!($(
($fhe_narrow, $fhe_wide, $scalar_narrow, $scalar_wide),
)*);
crate::high_level_api::integers::unsigned::fused_ops::impl_fused_scalar_mul_scalar_div!($(
($fhe_narrow, $fhe_wide, $scalar_narrow, $scalar_wide),
)*);
}
}
pub(crate) use impl_fused_mul_divs;
// Standard types (always available)
//
// (NarrowFhe, WideFhe, NarrowScalar, WideScalar)
//
// Types without at least double-width FheUint (FheUint2048) are not supported.
impl_fused_mul_divs!(
(super::FheUint2, super::FheUint4, u8, u8),
(super::FheUint4, super::FheUint8, u8, u8),
(super::FheUint6, super::FheUint12, u8, u16),
(super::FheUint8, super::FheUint16, u8, u16),
(super::FheUint10, super::FheUint32, u16, u32),
(super::FheUint12, super::FheUint32, u16, u32),
(super::FheUint14, super::FheUint32, u16, u32),
(super::FheUint16, super::FheUint32, u16, u32),
(super::FheUint32, super::FheUint64, u32, u64),
(super::FheUint64, super::FheUint128, u64, u128),
(super::FheUint128, super::FheUint256, u128, U256),
(super::FheUint160, super::FheUint512, U256, U512),
(super::FheUint256, super::FheUint512, U256, U512),
(super::FheUint512, super::FheUint1024, U512, U1024),
(super::FheUint1024, super::FheUint2048, U1024, U2048),
);
#[cfg(feature = "extended-types")]
impl_fused_mul_divs!(
(super::FheUint24, super::FheUint48, u32, u64),
(super::FheUint40, super::FheUint80, u64, u128),
(super::FheUint48, super::FheUint96, u64, u128),
(super::FheUint56, super::FheUint112, u64, u128),
(super::FheUint72, super::FheUint144, u128, U256),
(super::FheUint80, super::FheUint160, u128, U256),
(super::FheUint88, super::FheUint176, u128, U256),
(super::FheUint96, super::FheUint192, u128, U256),
(super::FheUint104, super::FheUint208, u128, U256),
(super::FheUint112, super::FheUint224, u128, U256),
(super::FheUint120, super::FheUint240, u128, U256),
(super::FheUint136, super::FheUint512, U256, U512),
(super::FheUint144, super::FheUint512, U256, U512),
(super::FheUint152, super::FheUint512, U256, U512),
(super::FheUint168, super::FheUint512, U256, U512),
(super::FheUint176, super::FheUint512, U256, U512),
(super::FheUint184, super::FheUint512, U256, U512),
(super::FheUint192, super::FheUint512, U256, U512),
(super::FheUint200, super::FheUint512, U256, U512),
(super::FheUint208, super::FheUint512, U256, U512),
(super::FheUint216, super::FheUint512, U256, U512),
(super::FheUint224, super::FheUint512, U256, U512),
(super::FheUint232, super::FheUint512, U256, U512),
(super::FheUint240, super::FheUint512, U256, U512),
(super::FheUint248, super::FheUint512, U256, U512),
);

View File

@@ -32,7 +32,6 @@ mod squashed_noise;
mod static_;
mod encrypt;
pub(in crate::high_level_api) mod fused_ops;
mod inner;
mod ops;
mod overflowing_ops;

View File

@@ -703,9 +703,3 @@ fn test_match_value_or() {
let client_key = setup_default_cpu();
super::test_case_match_value_or(&client_key);
}
#[test]
fn test_uint16_fused_mul_div() {
let client_key = setup_default_cpu();
super::test_case_uint16_fused_mul_div(&client_key);
}

View File

@@ -1004,11 +1004,3 @@ fn test_gpu_get_match_value_or_size_on_gpu() {
assert!(memory_size > 0);
}
}
#[test]
fn test_uint16_fused_mul_div_gpu() {
for setup_fn in GPU_SETUP_FN {
let client_key = setup_fn();
super::test_case_uint16_fused_mul_div(&client_key);
}
}

View File

@@ -1,9 +1,7 @@
use crate::high_level_api::traits::BitSlice;
use crate::integer::U256;
use crate::prelude::*;
use crate::{
ClientKey, FheBool, FheUint16, FheUint256, FheUint32, FheUint64, FheUint8, MatchValues,
};
use crate::{ClientKey, FheBool, FheUint256, FheUint32, FheUint64, FheUint8, MatchValues};
use rand::{thread_rng, Rng};
use std::collections::HashMap;
@@ -912,66 +910,3 @@ fn test_case_match_value_or(cks: &ClientKey) {
);
}
}
fn test_case_uint16_fused_mul_div(cks: &ClientKey) {
let mut rng = rand::thread_rng();
// Widening prevents incorrect result:
// 300 * 300 = 90_000 which overflows u16 (max 65_535),
// but with widening: 90_000 / 100 = 900, correct.
{
let input = 300u16;
let mul = 300u16;
let div = 100u16;
let expected = 900u16;
let a = FheUint16::try_encrypt(input, cks).unwrap();
let b = FheUint16::try_encrypt(mul, cks).unwrap();
let result = (&a).fused_mul_scalar_div(&b, div);
let decrypted: u16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
let result = (&a).fused_scalar_mul_scalar_div(mul, div);
let decrypted: u16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
for _ in 0..5 {
let clear_a: u16 = rng.gen();
let clear_b: u16 = rng.gen();
let clear_c: u16 = rng.gen_range(1..=u16::MAX);
let a = FheUint16::try_encrypt(clear_a, cks).unwrap();
let b = FheUint16::try_encrypt(clear_b, cks).unwrap();
let expected = (u32::from(clear_a) * u32::from(clear_b) / u32::from(clear_c)) as u16;
// encrypted * encrypted / scalar
{
let result = (&a).fused_mul_scalar_div(&b, clear_c);
let decrypted: u16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
// encrypted * scalar / scalar
{
let result = (&a).fused_scalar_mul_scalar_div(clear_b, clear_c);
let decrypted: u16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
// Owned variants
{
let result = a.fused_mul_scalar_div(b, clear_c);
let decrypted: u16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
// Need to encrypt again since "a" was consumed above
let a = FheUint16::try_encrypt(clear_a, cks).unwrap();
let result = a.fused_scalar_mul_scalar_div(clear_b, clear_c);
let decrypted: u16 = result.decrypt(cks);
assert_eq!(decrypted, expected);
}
}
}

View File

@@ -107,9 +107,9 @@ expand_pub_use_fhe_type!(
};
);
pub use array::{
fhe_array_contains, ClearArray, CpuFheIntArray, CpuFheIntSlice, CpuFheIntSliceMut,
CpuFheUintArray, CpuFheUintSlice, CpuFheUintSliceMut, FheBoolId, FheIntArray, FheIntSlice,
FheIntSliceMut, FheUintArray, FheUintSlice, FheUintSliceMut,
ClearArray, CpuFheIntArray, CpuFheIntSlice, CpuFheIntSliceMut, CpuFheUintArray,
CpuFheUintSlice, CpuFheUintSliceMut, FheBoolId, FheIntArray, FheIntSlice, FheIntSliceMut,
FheUintArray, FheUintSlice, FheUintSliceMut,
};
export_concrete_array_types!(
pub use array{

View File

@@ -8,10 +8,10 @@
//! ```
pub use crate::high_level_api::traits::{
BitSlice, CiphertextList, DivRem, FheDecrypt, FheEncrypt, FheEq, FheKeyswitch, FheMax, FheMin,
FheOrd, FheTrivialEncrypt, FheTryEncrypt, FheTryTrivialEncrypt, FheWait, Flip,
FusedMulScalarDiv, FusedScalarMulScalarDiv, IfThenElse, IfThenZero, OverflowingAdd,
OverflowingMul, OverflowingNeg, OverflowingSub, ReRandomize, RotateLeft, RotateLeftAssign,
RotateRight, RotateRightAssign, ScalarIfThenElse, SquashNoise, Tagged,
FheOrd, FheTrivialEncrypt, FheTryEncrypt, FheTryTrivialEncrypt, FheWait, Flip, IfThenElse,
IfThenZero, OverflowingAdd, OverflowingMul, OverflowingNeg, OverflowingSub, ReRandomize,
RotateLeft, RotateLeftAssign, RotateRight, RotateRightAssign, ScalarIfThenElse, SquashNoise,
Tagged,
};
#[cfg(feature = "hpu")]
pub use crate::high_level_api::traits::{FheHpu, HpuHandle};

View File

@@ -325,121 +325,6 @@ fn execute_re_rand_test(cks: &ClientKey, cpk: &CompactPublicKey) {
}
}
#[cfg(feature = "zk-pok")]
mod zk {
use super::*;
use crate::high_level_api::{FheInt64, FheUint32};
use crate::zk::{CompactPkeCrs, ZkComputeLoad};
use crate::{Config, ProvenCompactCiphertextList};
#[test]
fn test_compact_list_re_rand() {
use crate::shortint::parameters::test_params::TEST_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128;
let params = TEST_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128;
let (cks, sks, cpk) = setup_re_rand_test(params);
set_server_key(sks.decompress());
let config = Config::from(params);
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
let rerand_domain_separator = *b"TFHE_Rrd";
// Intentionally low so that we test when multiple lists and proofs are needed
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
// Case where we want to re-randomize a CompactCiphertextList containing
// FheUint64, FheInt8, and FheBool
{
let clear_a = rand::random::<u64>();
let clear_b = rand::random::<i8>();
let compact_list = ProvenCompactCiphertextList::builder(&cpk)
.push(clear_a)
.push(clear_b)
.push(false)
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
.unwrap();
// Simulate a 256 bits nonce
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
let mut re_rand_context = ReRandomizationContext::new(
rerand_domain_separator,
[b"expand".as_slice(), nonce.as_slice()],
compact_public_encryption_domain_separator,
);
// Add the compact list to the context
re_rand_context.add_ciphertext(&compact_list);
let mut seed_gen = re_rand_context.finalize();
// Verify, re_randomize and expand
let expander = compact_list
.verify_re_randomize_and_expand(
&crs,
&cpk,
&metadata,
seed_gen.next_seed().unwrap(),
)
.unwrap();
let a: FheUint64 = expander.get(0).unwrap().unwrap();
let b: FheInt8 = expander.get(1).unwrap().unwrap();
let c: FheBool = expander.get(2).unwrap().unwrap();
let dec_a: u64 = a.decrypt(&cks);
assert_eq!(dec_a, clear_a);
let dec_b: i8 = b.decrypt(&cks);
assert_eq!(dec_b, clear_b);
let dec_c: bool = c.decrypt(&cks);
assert!(!dec_c);
}
// Also test expand_and_re_randomize_without_verification
{
let clear_a = rand::random::<u32>();
let clear_b = rand::random::<i64>();
let compact_list = ProvenCompactCiphertextList::builder(&cpk)
.push(clear_a)
.push(clear_b)
.push(false)
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
.unwrap();
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
let mut re_rand_context = ReRandomizationContext::new(
rerand_domain_separator,
[b"expand".as_slice(), nonce.as_slice()],
compact_public_encryption_domain_separator,
);
re_rand_context.add_ciphertext(&compact_list);
let mut seed_gen = re_rand_context.finalize();
let expander = compact_list
.re_randomize_and_expand_without_verification(&cpk, seed_gen.next_seed().unwrap())
.unwrap();
let a: FheUint32 = expander.get(0).unwrap().unwrap();
let b: FheInt64 = expander.get(1).unwrap().unwrap();
let c: FheBool = expander.get(2).unwrap().unwrap();
let dec_a: u32 = a.decrypt(&cks);
assert_eq!(dec_a, clear_a);
let dec_b: i64 = b.decrypt(&cks);
assert_eq!(dec_b, clear_b);
let dec_c: bool = c.decrypt(&cks);
assert!(!dec_c);
}
}
}
fn setup_re_rand_test(
mut params: MetaParameters,
) -> (crate::ClientKey, CompressedServerKey, CompactPublicKey) {

View File

@@ -139,30 +139,6 @@ pub trait DivRem<Rhs = Self> {
fn div_rem(self, amount: Rhs) -> Self::Output;
}
/// Computes `(self * mul) / div_scalar` where `self` and `mul` are encrypted and `div_scaalr` is a
/// plaintext divisor.
///
/// The intermediate multiplication is performed to have the exact result without overflowing.
/// The final result is truncated back to the original width, which may wrap if the full precision
/// division result does not fit in the original type.
pub trait FusedMulScalarDiv<Mul, DivScalar> {
type Output;
fn fused_mul_scalar_div(self, mul: Mul, div_scalar: DivScalar) -> Self::Output;
}
/// Computes `(self * mul_scalar) / div_scalar` where `self` is encrypted and both scalars are
/// plaintext.
///
/// The intermediate multiplication is performed to have the exact result without overflowing.
/// The final result is truncated back to the original width, which may wrap if the full precision
/// division result does not fit in the original type.
pub trait FusedScalarMulScalarDiv<Scalar> {
type Output;
fn fused_scalar_mul_scalar_div(self, mul_scalar: Scalar, div_scalar: Scalar) -> Self::Output;
}
pub trait IfThenElse<Ciphertext> {
fn if_then_else(&self, ct_then: &Ciphertext, ct_else: &Ciphertext) -> Ciphertext;
fn select(&self, ct_when_true: &Ciphertext, ct_when_false: &Ciphertext) -> Ciphertext {

View File

@@ -421,28 +421,10 @@ impl<const N: usize> From<(u64, u64, u64, u64)> for StaticSignedBigInt<N> {
}
}
impl<const N_IN: usize, const N_OUT: usize> CastFrom<StaticSignedBigInt<N_IN>>
for StaticSignedBigInt<N_OUT>
{
fn cast_from(input: StaticSignedBigInt<N_IN>) -> Self {
// Get rid of special case, will be removed at compile time, no runtime impact
if N_IN == 0 {
return Self::ZERO;
}
// Safe to unwrap, N_IN > 0
let sign = input.0.last().unwrap() >> 63;
// If sign == 1, i.e. top bit was set, then the BigInt was negative, taking the wrapping_neg
// yields u64::MAX == -1 == 0xffffffffffffffff, if sign == 0, wrapping_neg does nothing and
// we get 0, this is a branchless way of getting the fill u64 for sign extension
let fill = sign.wrapping_neg();
let smallest = N_IN.min(N_OUT);
// init data with fill will naturally sign extend as required, since the low bits will be
// copied and the high bits will be 1s or 0s depending on sign
let mut data = [fill; N_OUT];
data[..smallest].copy_from_slice(&input.0[..smallest]);
Self(data)
impl<const N: usize> CastFrom<Self> for StaticSignedBigInt<N> {
#[inline(always)]
fn cast_from(input: Self) -> Self {
input
}
}
@@ -495,36 +477,6 @@ impl<const N: usize> CastFrom<u128> for StaticSignedBigInt<N> {
}
}
impl<const N: usize> CastFrom<i8> for StaticSignedBigInt<N> {
fn cast_from(input: i8) -> Self {
Self::from(input as i128)
}
}
impl<const N: usize> CastFrom<i16> for StaticSignedBigInt<N> {
fn cast_from(input: i16) -> Self {
Self::from(input as i128)
}
}
impl<const N: usize> CastFrom<i32> for StaticSignedBigInt<N> {
fn cast_from(input: i32) -> Self {
Self::from(input as i128)
}
}
impl<const N: usize> CastFrom<i64> for StaticSignedBigInt<N> {
fn cast_from(input: i64) -> Self {
Self::from(input as i128)
}
}
impl<const N: usize> CastFrom<i128> for StaticSignedBigInt<N> {
fn cast_from(input: i128) -> Self {
Self::from(input)
}
}
impl<const N: usize> CastFrom<StaticSignedBigInt<N>> for u8 {
fn cast_from(input: StaticSignedBigInt<N>) -> Self {
input.0[0] as Self
@@ -588,31 +540,12 @@ mod test {
#[test]
fn test_i128_cast() {
{
let a = 1_i128 << 64;
let a = 1_i128 << 64;
let b: StaticSignedBigInt<4> = a.into();
let b: StaticSignedBigInt<4> = a.into();
let c = i128::cast_from(b);
let c = i128::cast_from(b);
assert_eq!(a, c);
}
{
let a = -1_i128 << 64;
let b: StaticSignedBigInt<4> = a.into();
let c = i128::cast_from(b);
assert_eq!(a, c);
assert_eq!(b, StaticSignedBigInt::<4>::ONE.wrapping_neg() << 64u32);
let d = StaticSignedBigInt::<5>::cast_from(b);
let e = i128::cast_from(d);
assert_eq!(a, e);
assert_eq!(d, StaticSignedBigInt::<5>::ONE.wrapping_neg() << 64u32);
}
assert_eq!(a, c);
}
}

View File

@@ -1,5 +1,3 @@
#[cfg(feature = "zk-pok")]
use super::ReRandomizationSeed;
use super::{DataKind, Expandable};
use crate::conformance::{ListSizeConstraint, ParameterSetConformant};
use crate::core_crypto::prelude::{LweCiphertextListConformanceParams, Numeric};
@@ -1111,32 +1109,6 @@ impl ProvenCompactCiphertextList {
self.expand_without_verification(expansion_mode)
}
pub fn verify_re_randomize_and_expand(
&self,
crs: &CompactPkeCrs,
public_key: &CompactPublicKey,
metadata: &[u8],
expansion_mode: IntegerCompactCiphertextListExpansionMode<'_>,
seed: ReRandomizationSeed,
) -> crate::Result<CompactCiphertextListExpander> {
if self.verify(crs, public_key, metadata) == ZkVerificationOutcome::Invalid {
return Err(crate::ErrorKind::InvalidZkProof.into());
}
self.re_randomize_and_expand_without_verification(expansion_mode, public_key, seed)
}
pub fn re_randomize(
&mut self,
public_key: &CompactPublicKey,
seed: ReRandomizationSeed,
) -> crate::Result<()> {
public_key.key.re_randomize_compact_ciphertext_lists(
self.ct_list.proved_lists.iter_mut().map(|(list, _)| list),
seed,
)
}
#[doc(hidden)]
/// This function allows to expand a ciphertext without verifying the associated proof.
///
@@ -1170,23 +1142,6 @@ is not"
))
}
#[doc(hidden)]
/// This function allows to re_randomize and expand a ciphertext without verifying the
/// associated proof.
///
/// If you are here you were probably looking for it: use at your own risks.
pub fn re_randomize_and_expand_without_verification(
&self,
expansion_mode: IntegerCompactCiphertextListExpansionMode<'_>,
public_key: &CompactPublicKey,
seed: ReRandomizationSeed,
) -> crate::Result<CompactCiphertextListExpander> {
let mut rerandomized = self.clone();
rerandomized.re_randomize(public_key, seed)?;
rerandomized.expand_without_verification(expansion_mode)
}
pub fn is_packed(&self) -> bool {
if self.is_empty() {
return false;

View File

@@ -8,9 +8,6 @@ pub use crate::shortint::ciphertext::{ReRandomizationSeed, ReRandomizationSeedHa
use crate::shortint::Ciphertext;
use crate::Result;
#[cfg(feature = "zk-pok")]
use super::ProvenCompactCiphertextList;
#[derive(Clone, Copy)]
pub enum ReRandomizationKey<'key> {
LegacyDedicatedCPK {
@@ -109,26 +106,6 @@ impl ReRandomizationContext {
self.ct_count += 1;
}
#[cfg(feature = "zk-pok")]
pub fn add_proven_ciphertext_list(&mut self, list: &ProvenCompactCiphertextList) {
self.ct_coeffs_buffer.extend(
list.ct_list
.proved_lists
.iter()
.flat_map(|list| list.0.ct_list.as_ref()),
);
self.meta_buffer.extend(
list.ct_list
.proved_lists
.iter()
.flat_map(|list| list.1.to_le_bytes()),
);
// We draw only one seed for the full list
self.ct_count += 1;
}
/// Add a metadata buffer to the context.
///
/// These bytes will be added to a temporary buffer and will only be hashed during the

View File

@@ -219,258 +219,3 @@ fn test_ciphertext_re_randomization_after_compression_impl(
}
}
}
#[cfg(feature = "zk-pok")]
mod zk {
use crate::core_crypto::prelude::LweCiphertextCount;
use crate::integer::ciphertext::{ProvenCompactCiphertextList, ReRandomizationContext};
use crate::integer::key_switching_key::KeySwitchingKey;
use crate::integer::parameters::IntegerCompactCiphertextListExpansionMode;
use crate::integer::{
BooleanBlock, ClientKey, CompactPrivateKey, CompactPublicKey, RadixCiphertext, ServerKey,
SignedRadixCiphertext,
};
use crate::shortint::parameters::test_params::{
TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2,
};
use crate::zk::{CompactPkeCrs, ZkComputeLoad};
use rand::Rng;
#[test]
fn test_proven_compact_ciphertext_list_re_randomization() {
let pke_params = TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
let ksk_params = TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let fhe_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let num_blocks = 4usize;
let metadata = [b't', b'e', b's', b't'];
let rerand_domain_separator = *b"TFHE_Rrd";
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
let cks = ClientKey::new(fhe_params);
let sks = ServerKey::new_radix_server_key(&cks);
let compact_private_key = CompactPrivateKey::new(pke_params);
let ksk = KeySwitchingKey::new((&compact_private_key, None), (&cks, &sks), ksk_params);
let pk = CompactPublicKey::new(&compact_private_key);
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(512)).unwrap();
let mut rng = rand::thread_rng();
let message_modulus = pke_params.message_modulus.0 as u128;
// Unsigned
{
let modulus = message_modulus.pow(num_blocks as u32);
let message = rng.gen::<u128>() % modulus;
let mut builder = ProvenCompactCiphertextList::builder(&pk);
builder.push_with_num_blocks(message, num_blocks);
let proven_ct = builder
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
.unwrap();
let mut re_rand_context = ReRandomizationContext::new(
rerand_domain_separator,
[metadata.as_slice()],
compact_public_encryption_domain_separator,
);
re_rand_context.add_proven_ciphertext_list(&proven_ct);
let mut seed_gen = re_rand_context.finalize();
let mut re_randomized = proven_ct.clone();
re_randomized
.re_randomize(&pk, seed_gen.next_seed().unwrap())
.unwrap();
assert!(proven_ct != re_randomized);
let expander = re_randomized
.expand_without_verification(
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(
ksk.as_view(),
),
)
.unwrap();
let expanded: RadixCiphertext = expander.get(0).unwrap().unwrap();
let decrypted: u128 = cks.decrypt_radix(&expanded);
assert_eq!(decrypted, message);
}
// Signed
{
let modulus = message_modulus.pow((num_blocks - 1) as u32) as i128;
let message = rng.gen::<i128>() % modulus;
let mut builder = ProvenCompactCiphertextList::builder(&pk);
builder.push_with_num_blocks(message, num_blocks);
let proven_ct = builder
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
.unwrap();
let mut re_rand_context = ReRandomizationContext::new(
rerand_domain_separator,
[metadata.as_slice()],
compact_public_encryption_domain_separator,
);
re_rand_context.add_proven_ciphertext_list(&proven_ct);
let mut seed_gen = re_rand_context.finalize();
let mut re_randomized = proven_ct.clone();
re_randomized
.re_randomize(&pk, seed_gen.next_seed().unwrap())
.unwrap();
assert!(proven_ct != re_randomized);
let expander = re_randomized
.expand_without_verification(
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(
ksk.as_view(),
),
)
.unwrap();
let expanded: SignedRadixCiphertext = expander.get(0).unwrap().unwrap();
let decrypted: i128 = cks.decrypt_signed_radix(&expanded);
assert_eq!(decrypted, message);
}
// Boolean
{
for message in [false, true] {
let mut builder = ProvenCompactCiphertextList::builder(&pk);
builder.push(message);
let proven_ct = builder
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
.unwrap();
let mut re_rand_context = ReRandomizationContext::new(
rerand_domain_separator,
[metadata.as_slice()],
compact_public_encryption_domain_separator,
);
re_rand_context.add_proven_ciphertext_list(&proven_ct);
let mut seed_gen = re_rand_context.finalize();
let mut re_randomized = proven_ct.clone();
re_randomized
.re_randomize(&pk, seed_gen.next_seed().unwrap())
.unwrap();
assert!(proven_ct != re_randomized);
let expander = re_randomized
.expand_without_verification(
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(
ksk.as_view(),
),
)
.unwrap();
let expanded: BooleanBlock = expander.get(0).unwrap().unwrap();
let decrypted = cks.decrypt_bool(&expanded);
assert_eq!(decrypted, message);
}
}
}
#[cfg(feature = "gpu")]
#[test]
fn test_proven_compact_ciphertext_list_re_rand_cpu_gpu_compatibility() {
use crate::core_crypto::gpu::CudaStreams;
use crate::integer::gpu::zk::CudaProvenCompactCiphertextList;
use crate::shortint::parameters::test_params::TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
let pke_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
let compact_private_key = CompactPrivateKey::new(pke_params);
let pk = CompactPublicKey::new(&compact_private_key);
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
let rerand_domain_separator = *b"TFHE_Rrd";
// Intentionally low so that we test when multiple lists and proofs are needed
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(8)).unwrap();
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
let clear_a = rand::random::<u64>();
let clear_b = rand::random::<i8>();
let proven_ct = ProvenCompactCiphertextList::builder(&pk)
.push(clear_a)
.push(clear_b)
.push(false)
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
.unwrap();
// Clone the list so both CPU and GPU start from the same state
let mut cpu_list = proven_ct.clone();
// Simulate a 256 bits nonce
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
// Create two identical seeds from the same context inputs
let cpu_seed = {
let mut ctx = ReRandomizationContext::new(
rerand_domain_separator,
[b"expand".as_slice(), nonce.as_slice()],
compact_public_encryption_domain_separator,
);
ctx.add_proven_ciphertext_list(&proven_ct);
ctx.finalize().next_seed().unwrap()
};
let gpu_seed = {
let mut ctx = ReRandomizationContext::new(
rerand_domain_separator,
[b"expand".as_slice(), nonce.as_slice()],
compact_public_encryption_domain_separator,
);
ctx.add_proven_ciphertext_list(&proven_ct);
ctx.finalize().next_seed().unwrap()
};
// Re-randomize on CPU
cpu_list.re_randomize(&pk, cpu_seed).unwrap();
// Re-randomize on GPU
let streams = CudaStreams::new_multi_gpu();
let mut gpu_list = CudaProvenCompactCiphertextList::from_proven_compact_ciphertext_list(
&proven_ct, &streams,
);
gpu_list.re_randomize(&pk, gpu_seed, &streams).unwrap();
// Read ciphertext data back from GPU and reconstruct an integer proven list
let gpu_compact_lists = gpu_list
.d_flattened_compact_lists
.to_vec_shortint_compact_ciphertext_list(&streams)
.unwrap();
let gpu_proved_lists: Vec<_> = gpu_compact_lists
.into_iter()
.zip(gpu_list.h_proved_lists.ct_list.proved_lists.iter())
.map(|(ct, (_, proof))| (ct, proof.clone()))
.collect();
let gpu_on_cpu = ProvenCompactCiphertextList {
ct_list: crate::shortint::ciphertext::ProvenCompactCiphertextList {
proved_lists: gpu_proved_lists,
},
info: gpu_list.h_proved_lists.info.clone(),
};
assert!(cpu_list == gpu_on_cpu);
}
}

View File

@@ -1,7 +1,6 @@
use crate::core_crypto::algorithms::verify_lwe_compact_ciphertext_list;
use crate::core_crypto::gpu::CudaStreams;
use crate::core_crypto::prelude::{CiphertextModulus, LweCiphertextCount};
use crate::integer::ciphertext::ReRandomizationSeed;
use crate::integer::gpu::ciphertext::compact_list::{
CudaCompactCiphertextListExpander, CudaFlattenedVecCompactCiphertextList,
};
@@ -65,42 +64,6 @@ impl CudaProvenCompactCiphertextList {
Err(crate::ErrorKind::InvalidZkProof.into())
}
pub fn verify_re_randomize_and_expand(
&self,
crs: &CompactPkeCrs,
public_key: &CompactPublicKey,
metadata: &[u8],
key: &CudaKeySwitchingKey,
seed: ReRandomizationSeed,
streams: &CudaStreams,
) -> crate::Result<CudaCompactCiphertextListExpander> {
let (all_valid, r) = rayon::join(
|| {
self.h_proved_lists
.ct_list
.proved_lists
.par_iter()
.all(|(ct_list, proof)| {
verify_lwe_compact_ciphertext_list(
&ct_list.ct_list,
&public_key.key.key,
proof,
crs,
metadata,
)
.is_valid()
})
},
|| self.re_randomize_and_expand_without_verification(key, public_key, seed, streams),
);
if all_valid {
return r;
}
Err(crate::ErrorKind::InvalidZkProof.into())
}
/// # Safety
///
/// - [CudaStreams::synchronize] __must__ be called after this function as soon as
@@ -114,46 +77,6 @@ impl CudaProvenCompactCiphertextList {
.expand(key, super::ZKType::Casting, streams)
}
/// # Safety
///
/// - [CudaStreams::synchronize] __must__ be called after this function as soon as
/// synchronization is required
pub fn re_randomize_and_expand_without_verification(
&self,
key: &CudaKeySwitchingKey,
public_key: &CompactPublicKey,
seed: ReRandomizationSeed,
streams: &CudaStreams,
) -> crate::Result<CudaCompactCiphertextListExpander> {
let mut rerandomized = self.duplicate(streams);
rerandomized.re_randomize(public_key, seed, streams)?;
rerandomized.expand_without_verification(key, streams)
}
pub fn re_randomize(
&mut self,
public_key: &CompactPublicKey,
seed: ReRandomizationSeed,
streams: &CudaStreams,
) -> crate::Result<()> {
self.h_proved_lists.re_randomize(public_key, seed)?;
let cpu_lists = self
.h_proved_lists
.ct_list
.proved_lists
.iter()
.map(|(list, _)| list.clone())
.collect();
self.d_flattened_compact_lists =
CudaFlattenedVecCompactCiphertextList::from_vec_shortint_compact_ciphertext_list(
cpu_lists,
self.h_proved_lists.info.clone(),
streams,
);
Ok(())
}
pub fn from_proven_compact_ciphertext_list(
h_proved_lists: &ProvenCompactCiphertextList,
streams: &CudaStreams,

View File

@@ -1,712 +0,0 @@
use crate::integer::prelude::ServerKeyDefaultCMux;
use crate::integer::server_key::radix_parallel::ilog2::{BitValue, Direction};
use crate::integer::{BooleanBlock, IntegerCiphertext, RadixCiphertext, ServerKey};
use crate::shortint::ciphertext::Degree;
use crate::shortint::server_key::LookupTableOwned;
use crate::shortint::{CarryModulus, Ciphertext, MessageModulus};
use rayon::prelude::*;
impl ServerKey {
pub(crate) fn count_consecutive_bits_2_2_unsigned(
&self,
in_ct: &RadixCiphertext,
direction: Direction,
bit_value: BitValue,
) -> RadixCiphertext {
assert_eq!(self.message_modulus(), MessageModulus(4));
assert_eq!(self.carry_modulus(), CarryModulus(4));
let input_num_bits = 2 * in_ct.blocks.len();
// output
let num_output_bits = (input_num_bits as f64 + 1.).log2().ceil() as usize;
let num_output_blocks = num_output_bits.div_ceil(2);
let CountConsecutiveBitsResult { flag, mut digits } =
self.unchecked_count_consecutive_bits_2_2_unsigned(in_ct, direction, bit_value);
digits.resize(num_output_blocks, self.key.create_trivial(0));
let true_ct = RadixCiphertext::from_blocks(digits);
let condition = BooleanBlock::new_unchecked(flag);
self.if_then_else_parallelized(&condition, &true_ct, input_num_bits as u64)
}
// If there is at least one non zero/one bit in the input:
// - flag is 1
// - digits is the number of trailing/leading zeros/ones of the input
// Otherwise, the flag and the digits are equal to 0
//
// Let's explain how the algorithm works for leading zeros.
// Let's suppose we have a 64 bits input and
// the input is not 0 (this case works a bit differently).
// The result is on 6 bits grouped by 2 (b5_b4, b3_b2, b1_b0)
//
// b5_b4 is the index of the first (starting from MSB) group of 16 bits
// which has (at least) one bit equal to 1.
// (example, if b5_b4=0, then leading_zeros < 16 thus (at least) one of the 16 MSB is not 0).
// (example, if b5_b4=1, then 16 <= leading_zeros < 32 thus the 16 MSB are
// all 0 and (at least) one the one of the 16 next MSB is not 0).
//
// In this group of 16 bits:
// - b3_b2 is is the index of the first (starting from MSB) group of 4 bits which has (at
// least) one bit equal to 1
// In this group of 4 bits:
// - b1_b0 is is the index of the first (starting from MSB) bit equal to 1
//
// This is the top down view
//
// In the algorithm, we use the bottom up view.
// We compute the "b1_b0" of each group of 4 bits
// and a boolean flag to know if (at least) one of the bits are not 0.
//
// We then group by 16 bits.
// We compute the "b3_b2" of each group.
// It is the index of the first (starting from MSB) group of 4 with a non zero flag.
// We select its "b1_b0" among the 4 computed in the previous step.
// We now have "b3_b2_b1_b0" for each group of 16.
// We also need a flag to know if (at least) one of the bits are not 0.
//
// We now have 4 groups of 16.
// "b5_b4" is the index of the first (starting from MSB) group of 16 with a non zero flag.
// We select its "b3_b2_b1_b0" among the 4 computed in the previous step.
// We also compute a flag to know if (at least) one of the bits are not 0.
//
// We now have the final result
pub(crate) fn unchecked_count_consecutive_bits_2_2_unsigned(
&self,
in_ct: &RadixCiphertext,
direction: Direction,
bit_value: BitValue,
) -> CountConsecutiveBitsResult {
assert_eq!(self.message_modulus(), MessageModulus(4));
assert_eq!(self.carry_modulus(), CarryModulus(4));
if in_ct.blocks().is_empty() {
return CountConsecutiveBitsResult {
flag: self.key.create_trivial(0),
digits: Vec::new(),
};
}
let num_blocks_after_init = in_ct.blocks().len() as f64 / 2_f64;
let reductions_depth = num_blocks_after_init.log(4_f64).ceil() as usize;
let mut up_scale_digits: bool = reductions_depth % 2 == 1;
let digit_out_scale_init = if up_scale_digits { 2 } else { 0 };
let mut state: Vec<BlockState> = match direction {
Direction::Trailing => in_ct
.blocks()
.par_chunks(2)
.map(|chunk| self.pack_blocks_by_pair(chunk, direction, bit_value))
.enumerate()
.map(|(index, ct)| {
self.initial_state(&ct, index % 4, digit_out_scale_init, direction, bit_value)
})
.collect(),
// par_rchunk(2).enumerate().rev() to:
// - get a reverse index without changing the order
// - align chunk on the most significant blocks (if the last chunk has only one element)
Direction::Leading => in_ct
.blocks()
.par_rchunks(2)
.map(|chunk| self.pack_blocks_by_pair(chunk, direction, bit_value))
.enumerate()
.rev()
.map(|(reverse_index, ct)| {
self.initial_state(
&ct,
reverse_index % 4,
digit_out_scale_init,
direction,
bit_value,
)
})
.collect(),
};
while state.len() != 1 {
up_scale_digits = !up_scale_digits;
state = match direction {
Direction::Trailing => state
.par_chunks(4)
.enumerate()
.map(|(index, chunk)| {
self.reduce_blocks(chunk, index % 4, up_scale_digits, direction)
})
.collect(),
// par_rchunk(4).enumerate().rev() to:
// - get a reverse index without changing the order
// - align chunk on the most significant blocks (if the last chunk does not have 4
// elements)
Direction::Leading => state
.par_rchunks(4)
.enumerate()
.rev()
.map(|(reverse_index, chunk)| {
self.reduce_blocks(chunk, reverse_index % 4, up_scale_digits, direction)
})
.collect(),
};
}
assert!(!up_scale_digits);
let BlockState {
flag,
digits: digits_state,
} = state.pop().unwrap();
CountConsecutiveBitsResult {
flag,
digits: digits_state.select(self, up_scale_digits, direction),
}
}
fn pack_blocks_by_pair(
&self,
chunk: &[Ciphertext],
direction: Direction,
bit_value: BitValue,
) -> Ciphertext {
match chunk {
[chunk0, chunk1] => {
// chunk 1 is most significant, so we scale it to the carries
let mut result = self.key.unchecked_scalar_mul(chunk1, 4);
self.key.unchecked_add_assign(&mut result, chunk0);
result
}
[chunk0] => {
// We must pad in case the input has a even number of blocks
// The pad must not change the result
// This padding value will only have an impact on the final result if all other bits
// are equal to the given bit_value In this case, we want to pad
// with bits equal to the bit_value so the result is flag = 0,
// digits= [0, ..., 0] as specified
let padding_value = match bit_value {
BitValue::Zero => 0,
BitValue::One => 3,
};
match direction {
// We put the padding in the MSB
Direction::Trailing => self.key.unchecked_scalar_add(chunk0, 4 * padding_value),
// We put the padding in the LSB
Direction::Leading => {
let mut result = self.key.unchecked_scalar_mul(chunk0, 4);
self.key
.unchecked_scalar_add_assign(&mut result, padding_value);
result
}
}
}
_ => unreachable!(),
}
}
fn initial_state(
&self,
ct: &Ciphertext,
flag_out_scale: usize,
digit_out_scale: usize,
direction: Direction,
bit_value: BitValue,
) -> BlockState {
let (flag, new_digit) = rayon::join(
|| {
let lut_non_full_flag = self.lut_non_full_flag(flag_out_scale, bit_value);
self.key.apply_lookup_table(ct, &lut_non_full_flag)
},
|| {
let lut_new_digit = self.lut_new_digit_init(digit_out_scale, direction, bit_value);
self.key.apply_lookup_table(ct, &lut_new_digit)
},
);
BlockState {
flag,
digits: DigitsUnselected {
new_digit,
old_digits_to_select: Vec::new(),
},
}
}
// Put blocks of n digits from a slice to groups of 4
//
// Each group of 4 is reduced to a single block of (n+1) digits as such:
// The fist block with a non zero flag is selected.
// The new digits are the digits of this block to which we add the index of this selected block
fn reduce_blocks(
&self,
blocks: &[BlockState],
out_flag_scale: usize,
up_scale_digits: bool,
direction: Direction,
) -> BlockState {
let (in_flags, digits): (Vec<_>, Vec<_>) = blocks
.iter()
.map(
|BlockState {
flag,
digits: digits_state,
}| (flag, digits_state),
)
.unzip();
// old digits are one step behind the flag and new_digit
// so opposite scaling
let up_scale_old_digits = !up_scale_digits;
let ((flag, new_digit), old_digits_to_select) = rayon::join(
|| self.build_new_flag_and_digit(out_flag_scale, up_scale_digits, &in_flags),
|| self.reduce_digit_states(&digits, up_scale_old_digits, direction),
);
BlockState {
flag,
digits: DigitsUnselected {
new_digit,
old_digits_to_select,
},
}
}
// The input is expected to be (at most) 4 binary flags, scaled by 0, 1, 2, 3 (0_0_0_f, 0_0_f_0,
// 0_f_0_0, f_0_0_0) The new flag is 0 if all input flags are 0, 1 otherwise
// The new digit is the scaling of the smallest non zero flag, 0 otherwise
// The output does not depend on the order of the input flags (as they are all summed)
fn build_new_flag_and_digit(
&self,
out_flag_scale: usize,
up_scale_digits: bool,
flags: &[&Ciphertext],
) -> (Ciphertext, Ciphertext) {
let sum_flags = flags.iter().fold(self.key.create_trivial(0), |mut a, b| {
self.key.unchecked_add_assign(&mut a, b);
a
});
let out_digit_scale = if up_scale_digits { 2 } else { 0 };
rayon::join(
|| {
let lut_non_zero_flag = self.lut_non_zero_flag(out_flag_scale);
self.key.apply_lookup_table(&sum_flags, &lut_non_zero_flag)
},
|| {
let lut_new_digit = self.lut_new_digit_from_sum_flags(out_digit_scale);
self.key.apply_lookup_table(&sum_flags, &lut_new_digit)
},
)
}
fn reduce_digit_states(
&self,
states: &[&DigitsUnselected],
up_scale_digits: bool,
direction: Direction,
) -> Vec<DigitUnselected> {
// we'll want to select one of the lists of digits (Vec<Ciphertext>)
// we'll want unselected_list_of_digits[new_digit]
let unselected_list_of_digits: Vec<Vec<Ciphertext>> = states
.par_iter()
.map(|digits_unselected| digits_unselected.select(self, up_scale_digits, direction))
.collect();
// after transpose, each element is an UnselectedDigit (i.e. a list of digits to select
// from) we'll want
// [
// list_of_unselected_digits[0][new_digit],
// list_of_unselected_digits[1][new_digit],
// ...
// ]
let list_of_unselected_digits = transpose(unselected_list_of_digits);
list_of_unselected_digits
.into_iter()
.map(|digits_to_select_from| DigitUnselected {
digits_to_select_from,
})
.collect()
}
fn select_old_digit_lut(
&self,
up_scale_digits: bool,
selector: usize,
) -> crate::shortint::server_key::LookupTable<Vec<u64>> {
self.key.generate_lookup_table(|x: u64| {
let in_carries = x >> 2;
let in_message = x & 3;
// The input of the resulting LUT is supposed to have the old/new digits in
// carry/message depending on up_scale_digits
let (old_digit, new_digit) = if up_scale_digits {
(in_message, in_carries)
} else {
(in_carries, in_message)
};
if new_digit == selector as u64 {
if up_scale_digits {
old_digit << 2
} else {
old_digit
}
} else {
0
}
})
}
// build a lut which returns
// `0` if the 4 bits input is full of the bit_value (0000 for Zero or 1111 for One)
// `1 << out_scale` otherwise
fn lut_non_full_flag(&self, out_scale: usize, bit_value: BitValue) -> LookupTableOwned {
let full_value = match bit_value {
BitValue::Zero => 0,
BitValue::One => 15,
};
self.key
.generate_lookup_table(|x| u64::from(x != full_value) << out_scale)
}
fn lut_non_zero_flag(&self, out_scale: usize) -> LookupTableOwned {
self.key
.generate_lookup_table(|x| u64::from(x != 0) << out_scale)
}
// build a lut which
// return `0` if the input is full of the bit_value (0000 for Zero or 1111 for One)
// otherwise, return the trailing/leading zeros/ones of the 4 bits input, scaled by `out_scale`
fn lut_new_digit_init(
&self,
out_scale: usize,
direction: Direction,
bit_value: BitValue,
) -> LookupTableOwned {
self.key.generate_lookup_table(|x: u64| {
let full_value = match bit_value {
BitValue::Zero => 0,
BitValue::One => 15,
};
let input_precision = 4;
let leading_bits_to_ignore = u64::BITS - input_precision;
let new_digit = if x == full_value {
0
} else {
match (direction, bit_value) {
(Direction::Trailing, BitValue::Zero) => x.trailing_zeros(),
(Direction::Trailing, BitValue::One) => x.trailing_ones(),
(Direction::Leading, BitValue::Zero) => {
(x << leading_bits_to_ignore).leading_zeros()
}
(Direction::Leading, BitValue::One) => {
(x << leading_bits_to_ignore).leading_ones()
}
}
};
(new_digit as u64) << out_scale
})
}
// build a lut
// the input is expected to the sum of 4 binary flags, scaled by 0, 1, 2, 3 (0_0_0_f0 + 0_0_f1_0
// + 0_f2_0_0 + f3_0_0_0 = f3_f2_f1_f0) if all the flags are 0, the result if 0
// otherwise, the result is the index of the first of these flag which is not 0, starting by f0.
// this function is used in all cases (trailing/leading zeros/ones) in all steps expect the
// first one
fn lut_new_digit_from_sum_flags(&self, out_scale: usize) -> LookupTableOwned {
self.key.generate_lookup_table(|x: u64| {
let new_digit = if x == 0 { 0 } else { x.trailing_zeros() as u64 };
new_digit << out_scale
})
}
}
fn transpose<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>> {
if v.is_empty() {
return vec![];
}
let num_cols = v[0].len();
let mut row_iterators: Vec<_> = v.into_iter().map(|row| row.into_iter()).collect();
(0..num_cols)
.map(|_| {
row_iterators
.iter_mut()
.map(|row_iterator| row_iterator.next().unwrap())
.collect::<Vec<T>>()
})
.collect()
}
struct BlockState {
flag: Ciphertext,
digits: DigitsUnselected,
}
// When doing the reduction, we want to use the new_digit to select each unselected_digit
// We then add the new digit to the end of the list
struct DigitsUnselected {
new_digit: Ciphertext,
old_digits_to_select: Vec<DigitUnselected>,
}
impl DigitsUnselected {
fn select(
&self,
sk: &ServerKey,
up_scale_digits: bool,
direction: Direction,
) -> Vec<Ciphertext> {
let Self {
new_digit,
old_digits_to_select,
} = self;
let mut result: Vec<_> = old_digits_to_select
.par_iter()
.map(|digit| digit.select(new_digit, sk, up_scale_digits, direction))
.collect();
result.push(new_digit.clone());
result
}
}
// Stores a list of (at most) 4 ciphertexts each storing a digit in carries or messages
// This type is meant to be reduced to a single selected digit
struct DigitUnselected {
digits_to_select_from: Vec<Ciphertext>,
}
impl DigitUnselected {
fn select(
&self,
selector: &Ciphertext,
sk: &ServerKey,
up_scale_digits: bool,
direction: Direction,
) -> Ciphertext {
let digits_to_select_from: Vec<&Ciphertext> = match direction {
Direction::Trailing => self.digits_to_select_from.iter().collect(),
Direction::Leading => self.digits_to_select_from.iter().rev().collect(),
};
// Computation is sum_i( if i==selector { digits_to_select_from[i] } else {0} )
// Which gives digits_to_select_from[selector]
let mut result = digits_to_select_from
.par_iter()
.enumerate()
.map(|(i, old_digit)| {
let sum = sk.key.unchecked_add(old_digit, selector);
let acc = sk.select_old_digit_lut(up_scale_digits, i);
sk.key.apply_lookup_table(&sum, &acc)
})
.reduce(
|| sk.key.create_trivial(0),
|mut sum: Ciphertext, new: Ciphertext| {
sk.key.unchecked_add_assign(&mut sum, &new);
sum
},
);
result.degree = if up_scale_digits {
Degree(12)
} else {
Degree(3)
};
result
}
}
pub(crate) struct CountConsecutiveBitsResult {
#[allow(unused)]
pub(crate) flag: Ciphertext,
pub(crate) digits: Vec<Ciphertext>,
}
#[cfg(test)]
mod test {
use super::*;
use crate::integer::keycache::KEY_CACHE;
use crate::integer::{ClientKey, IntegerKeyKind, RadixCiphertext};
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
use rand::{thread_rng, Rng};
#[test]
fn test_unchecked_new_count_consecutive_bits_trivial_input_param_message_2_carry_2() {
let param = PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
let (cks, sks) = KEY_CACHE.get_from_params(param, IntegerKeyKind::Radix);
for direction in [Direction::Leading, Direction::Trailing] {
for bit_value in [BitValue::Zero, BitValue::One] {
for num_blocks in 1..64 {
let num_bits = 2 * num_blocks;
println!("num_bits: {num_bits}",);
for target_result in 0..=num_bits {
for _ in 0..10 {
test_one_random(
&cks,
&sks,
num_blocks,
direction,
bit_value,
target_result,
);
}
}
}
}
}
}
fn test_one_random(
cks: &ClientKey,
sks: &ServerKey,
num_blocks: usize,
direction: Direction,
bit_value: BitValue,
target_result: usize,
) {
let num_bits = 2 * num_blocks;
let message = build_number(num_bits, target_result, direction, bit_value);
let (expected_flag, expected_result) =
expected_result(num_bits, message, direction, bit_value);
let (flag, result) =
get_result_for_trivial(cks, sks, num_blocks, message, direction, bit_value);
assert_eq!(expected_flag, flag);
if target_result == num_bits {
assert!(!expected_flag);
assert_eq!(expected_result, 0);
} else {
assert_eq!(target_result as u64, expected_result);
}
assert_eq!(expected_result, result);
}
fn expected_result(
num_bits: usize,
message: u128,
direction: Direction,
bit_value: BitValue,
) -> (bool, u64) {
let full_value = match bit_value {
BitValue::Zero => 0,
BitValue::One => (1 << num_bits) - 1,
};
if message == full_value {
(false, 0)
} else {
let leading_bits_to_ignore = 128 - num_bits;
let expected_result = match (direction, bit_value) {
(Direction::Trailing, BitValue::Zero) => message.trailing_zeros(),
(Direction::Trailing, BitValue::One) => message.trailing_ones(),
(Direction::Leading, BitValue::Zero) => {
(message << leading_bits_to_ignore).leading_zeros()
}
(Direction::Leading, BitValue::One) => {
(message << leading_bits_to_ignore).leading_ones()
}
};
(true, expected_result as u64)
}
}
fn build_number(
num_bits: usize,
target_result: usize,
direction: Direction,
bit_value: BitValue,
) -> u128 {
let full_bits = num_bits - target_result;
let message: u128 = if full_bits == 0 {
0
} else {
match direction {
Direction::Leading => {
(1_u128 << (full_bits - 1)) + thread_rng().gen_range(0..1 << (full_bits - 1))
}
Direction::Trailing => {
let full_number =
1_u128 + (thread_rng().gen_range(0..1 << (full_bits - 1)) << 1);
full_number << target_result
}
}
};
match bit_value {
BitValue::Zero => message,
//complement
BitValue::One => (1_u128 << num_bits) - 1 - message,
}
}
fn get_result_for_trivial(
cks: &ClientKey,
sks: &ServerKey,
num_blocks: usize,
message: u128,
direction: Direction,
bit_value: BitValue,
) -> (bool, u64) {
let input: RadixCiphertext = sks.create_trivial_radix(message, num_blocks);
let CountConsecutiveBitsResult { flag, digits } =
sks.unchecked_count_consecutive_bits_2_2_unsigned(&input, direction, bit_value);
let flag = match cks.key.decrypt_message_and_carry(&flag) {
0 => false,
1 => true,
_ => panic!(),
};
let mut result = 0;
for (i, digit) in digits.iter().enumerate() {
let digit = cks.key.decrypt_message_and_carry(digit);
result += digit << (2 * i);
}
(flag, result)
}
}

View File

@@ -2,7 +2,7 @@ use crate::integer::{
BooleanBlock, IntegerCiphertext, IntegerRadixCiphertext, RadixCiphertext, ServerKey,
SignedRadixCiphertext,
};
use crate::shortint::{CarryModulus, Ciphertext, MessageModulus};
use crate::shortint::Ciphertext;
use rayon::prelude::*;
/// A 'bit' value
@@ -140,12 +140,6 @@ impl ServerKey {
return self.create_trivial_zero_radix(0);
}
if self.message_modulus() == MessageModulus(4) && self.carry_modulus() == CarryModulus(4) {
let unsigned_ct = RadixCiphertext::from_blocks(ct.blocks().to_vec());
return self.count_consecutive_bits_2_2_unsigned(&unsigned_ct, direction, bit_value);
}
let num_bits_in_message = self.key.message_modulus.0.ilog2();
let original_num_blocks = ct.blocks().len();

View File

@@ -5,7 +5,6 @@ mod bitwise_op;
mod block_shift;
pub(crate) mod cmux;
mod comparison;
mod count_consecutive_bits;
mod div_mod;
mod modulus_switch_compression;
mod mul;

View File

@@ -10,7 +10,6 @@ use crate::core_crypto::commons::math::random::{DefaultRandomGenerator, XofSeed}
use crate::core_crypto::commons::parameters::{LweCiphertextCount, PlaintextCount};
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::{LweCiphertext, LweCompactCiphertextList, PlaintextList};
use crate::core_crypto::prelude::lwe_compact_ciphertext_list_add_assign;
use crate::shortint::ciphertext::NoiseLevel;
use crate::shortint::key_switching_key::KeySwitchingKeyMaterialView;
use crate::shortint::{Ciphertext, CompactPublicKey, PBSOrder};
@@ -19,8 +18,6 @@ use rayon::prelude::*;
use sha3::digest::{ExtendableOutput, Update};
use std::io::Read;
use super::CompactCiphertextList;
/// Size of the re-randomization seed in bits
const RERAND_SEED_BITS: usize = 256;
@@ -251,14 +248,6 @@ impl CompactPublicKey {
let mut encryption_generator =
NoiseRandomGenerator::<DefaultRandomGenerator>::new_from_seed(seed.0);
self.prepare_cpk_zero_for_rerand_with_generator(&mut encryption_generator, zero_count)
}
pub(crate) fn prepare_cpk_zero_for_rerand_with_generator(
&self,
encryption_generator: &mut NoiseRandomGenerator<DefaultRandomGenerator>,
zero_count: LweCiphertextCount,
) -> LweCompactCiphertextList<Vec<u64>> {
let mut encryption_of_zero = LweCompactCiphertextList::new(
0,
self.parameters().encryption_lwe_dimension.to_lwe_size(),
@@ -279,7 +268,7 @@ impl CompactPublicKey {
&plaintext_list,
cpk_encryption_noise_distribution,
cpk_encryption_noise_distribution,
encryption_generator,
&mut encryption_generator,
);
encryption_of_zero
@@ -321,7 +310,8 @@ impl CompactPublicKey {
KeySwitchingKeyMaterialView.";
return Err(crate::error!("{}", err));
} else if ksk_output_lwe_size != ct.ct.lwe_size() {
let err = "Mismatched LweSize between Ciphertext being re-randomized and provided \
let err =
"Mismatched LweSwize between Ciphertext being re-randomized and provided \
KeySwitchingKeyMaterialView.";
return Err(crate::error!("{}", err));
} else if ct.noise_level() > NoiseLevel::NOMINAL {
@@ -401,7 +391,7 @@ impl CompactPublicKey {
for ct in cts.iter() {
if key_lwe_size != ct.ct.lwe_size() {
let err = "Mismatched LweSize between Ciphertexts \
let err = "Mismatched LweSwize between Ciphertexts \
being re-randomized and provided CompactPublicKey";
return Err(crate::error!("{}", err));
} else if ct.noise_level() > NoiseLevel::NOMINAL {
@@ -427,54 +417,28 @@ impl CompactPublicKey {
Ok(())
}
/// Re-randomize compact ciphertext lists using the provided seed.
pub fn re_randomize_compact_ciphertext_lists<'a>(
&self,
compact_lists: impl Iterator<Item = &'a mut CompactCiphertextList>,
seed: ReRandomizationSeed,
) -> crate::Result<()> {
let key_lwe_size = self.key.lwe_dimension().to_lwe_size();
let mut encryption_generator =
NoiseRandomGenerator::<DefaultRandomGenerator>::new_from_seed(seed.0);
for list in compact_lists {
if key_lwe_size != list.ct_list.lwe_size() {
return Err(crate::error!(
"Mismatched LweSize between Compact Lists \
being re-randomized and provided CompactPublicKey",
));
}
let encryption_of_zero = self.prepare_cpk_zero_for_rerand_with_generator(
&mut encryption_generator,
list.ct_list.lwe_ciphertext_count(),
);
lwe_compact_ciphertext_list_add_assign(&mut list.ct_list, &encryption_of_zero);
}
Ok(())
}
}
#[cfg(test)]
mod test {
use rand::Rng;
use super::*;
use crate::shortint::ciphertext::ShortintCompactCiphertextListCastingMode;
use crate::shortint::key_switching_key::{KeySwitchingKeyBuildHelper, KeySwitchingKeyMaterial};
use crate::shortint::parameters::test_params::*;
use crate::shortint::parameters::test_params::{
TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2,
};
use crate::shortint::parameters::{
AtomicPatternParameters, CompactPublicKeyEncryptionParameters, ReRandomizationParameters,
PARAM_MESSAGE_2_CARRY_2_KS_PBS,
};
use crate::shortint::{gen_keys, CompactPrivateKey, KeySwitchingKeyView};
use crate::shortint::{gen_keys, CompactPrivateKey};
/// Test the case where we rerand more ciphertexts that what can be stored in one cpk lwe
/// Test the trivial case
#[test]
fn test_rerand_with_dedicated_cpk_ci_run_filter() {
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let compute_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS;
let cpk_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
let rerand_ksk_params =
TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
@@ -487,7 +451,7 @@ mod test {
#[test]
fn test_rerand_with_derived_cpk_ci_run_filter() {
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let compute_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS;
let rerand_params = ReRandomizationParameters::DerivedCPKWithoutKeySwitch;
test_rerand_impl(compute_params.into(), None, rerand_params);
@@ -596,125 +560,4 @@ mod test {
assert_eq!(dec, 3);
}
}
#[test]
fn test_rerand_compact_list_ci_run_filter() {
let mut rng = rand::thread_rng();
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let cpk_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
let ks_params = TEST_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
const CT_COUNT: usize = 37;
let (cks, sks) = gen_keys(compute_params);
let privk = CompactPrivateKey::new(cpk_params);
let pubk = CompactPublicKey::new(&privk);
let ksk_builder = KeySwitchingKeyBuildHelper::new((&privk, None), (&cks, &sks), ks_params);
let casting_key: KeySwitchingKeyView<'_> = ksk_builder.as_key_switching_key_view();
let casting_mode = ShortintCompactCiphertextListCastingMode::CastIfNecessary {
casting_key,
functions: None,
};
let messages: [u64; CT_COUNT] =
core::array::from_fn(|_| rng.gen_range(0..cpk_params.message_modulus.0));
let mut enc = pubk.encrypt_slice(&messages);
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rng.gen());
let mut re_rand_context = ReRandomizationContext::new(*b"TFHE_Rrd", *b"TFHE_Enc");
re_rand_context.add_ciphertext_data_slice(enc.ct_list.as_ref());
re_rand_context.add_bytes(&nonce);
re_rand_context.add_bytes(b"expand");
let mut seeder = re_rand_context.finalize();
pubk.re_randomize_compact_ciphertext_lists(std::iter::once(&mut enc), seeder.next_seed())
.unwrap();
let cast = enc.expand(casting_mode).unwrap();
assert_eq!(cast.len(), CT_COUNT);
for (ct, clear) in cast.iter().zip(&messages) {
assert_eq!(cks.decrypt(ct), *clear)
}
}
#[cfg(feature = "zk-pok")]
#[test]
fn test_rerand_proven_compact_list_ci_run_filter() {
use crate::zk::{CompactPkeCrs, ZkComputeLoad};
let mut rng = rand::thread_rng();
let compute_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let cpk_params = TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
let ks_params = TEST_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
// Make sure that the resulting proven list will be composed of multiple inner compact lists
const CT_COUNT: usize = 37;
let (cks, sks) = gen_keys(compute_params);
let privk = CompactPrivateKey::new(cpk_params);
let pubk = CompactPublicKey::new(&privk);
let crs = CompactPkeCrs::from_shortint_params(cpk_params, LweCiphertextCount(4)).unwrap();
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
let ksk_builder = KeySwitchingKeyBuildHelper::new((&privk, None), (&cks, &sks), ks_params);
let casting_key: KeySwitchingKeyView<'_> = ksk_builder.as_key_switching_key_view();
let id = |x: u64| x;
let dyn_id: &(dyn Fn(u64) -> u64 + Sync) = &id;
let functions = vec![Some(vec![dyn_id; 1]); CT_COUNT];
let casting_mode = ShortintCompactCiphertextListCastingMode::CastIfNecessary {
casting_key,
functions: Some(functions.as_slice()),
};
let messages: [u64; CT_COUNT] =
core::array::from_fn(|_| rng.gen_range(0..cpk_params.message_modulus.0));
let mut enc = pubk
.encrypt_and_prove_slice(
&messages,
&crs,
&metadata,
ZkComputeLoad::Verify,
cpk_params.message_modulus.0,
)
.unwrap();
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rng.gen());
let mut re_rand_context = ReRandomizationContext::new(*b"TFHE_Rrd", *b"TFHE_Enc");
re_rand_context.add_ciphertext_data_slice(
&enc.proved_lists
.iter()
.flat_map(|list| list.0.ct_list.as_ref())
.copied()
.collect::<Vec<_>>(),
);
re_rand_context.add_bytes(&nonce);
re_rand_context.add_bytes(b"expand");
let mut seeder = re_rand_context.finalize();
pubk.re_randomize_compact_ciphertext_lists(
enc.proved_lists.iter_mut().map(|(list, _)| list),
seeder.next_seed(),
)
.unwrap();
let cast = enc.expand_without_verification(casting_mode).unwrap();
assert_eq!(cast.len(), CT_COUNT);
for (ct, clear) in cast.iter().zip(&messages) {
assert_eq!(cks.decrypt(ct), *clear)
}
}
}

View File

@@ -183,7 +183,10 @@ impl ProvenCompactCiphertextList {
}
modes
}
None => vec![casting_mode; self.proved_lists.len()],
None => vec![
ShortintCompactCiphertextListCastingMode::NoCasting;
self.proved_lists.len()
],
},
ShortintCompactCiphertextListCastingMode::NoCasting => {
vec![ShortintCompactCiphertextListCastingMode::NoCasting; self.proved_lists.len()]
@@ -358,8 +361,7 @@ mod tests {
use crate::conformance::ParameterSetConformant;
use crate::core_crypto::prelude::LweCiphertextCount;
use crate::shortint::ciphertext::ProvenCompactCiphertextListConformanceParams;
use crate::shortint::parameters::test_params::*;
use crate::shortint::parameters::ShortintCompactCiphertextListCastingMode;
use crate::shortint::parameters::*;
use crate::shortint::{
ClientKey, CompactPrivateKey, CompactPublicKey, KeySwitchingKey, ServerKey,
};
@@ -370,9 +372,9 @@ mod tests {
#[test]
fn test_zk_ciphertext_encryption_ci_run_filter() {
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let ksk_params = TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let pke_params = PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(4)).unwrap();
let priv_key = CompactPrivateKey::new(pke_params);
@@ -432,9 +434,9 @@ mod tests {
#[test]
fn test_zk_compact_ciphertext_list_encryption_ci_run_filter() {
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let ksk_params = TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let pke_params = PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(4)).unwrap();
let priv_key = CompactPrivateKey::new(pke_params);
@@ -483,59 +485,10 @@ mod tests {
assert_eq!(msgs, decrypted);
}
/// Test a case where we need to keyswitch to compute params but no functions are applied
#[test]
fn test_zk_compact_ciphertext_list_encryption_no_fn_ci_run_filter() {
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let ksk_params = TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(4)).unwrap();
let priv_key = CompactPrivateKey::new(pke_params);
let pub_key = CompactPublicKey::new(&priv_key);
let ck = ClientKey::new(params);
let sk = ServerKey::new(&ck);
let ksk = KeySwitchingKey::new((&priv_key, None), (&ck, &sk), ksk_params);
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
let msgs = (0..512)
.map(|_| random::<u64>() % params.message_modulus.0)
.collect::<Vec<_>>();
let proven_ct = pub_key
.encrypt_and_prove_slice(
&msgs,
&crs,
&metadata,
ZkComputeLoad::Proof,
params.message_modulus.0,
)
.unwrap();
assert!(proven_ct.verify(&crs, &pub_key, &metadata).is_valid());
let expanded = proven_ct
.verify_and_expand(
&crs,
&pub_key,
&metadata,
ShortintCompactCiphertextListCastingMode::CastIfNecessary {
casting_key: ksk.as_view(),
functions: None,
},
)
.unwrap();
let decrypted = expanded
.iter()
.map(|ciphertext| ck.decrypt(ciphertext))
.collect::<Vec<_>>();
assert_eq!(msgs, decrypted);
}
#[test]
fn test_zk_proof_conformance_ci_run_filter() {
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let pke_params = TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let pke_params = PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let max_lwe_count_per_compact_list = LweCiphertextCount(320);
let total_lwe_count = 512;

View File

@@ -120,13 +120,13 @@ impl NoiseSquashingCompressionKey {
#[cfg(test)]
mod test {
use crate::shortint::ciphertext::{Degree, MaxDegree};
use crate::shortint::ciphertext::MaxDegree;
use crate::shortint::keycache::KEY_CACHE;
use crate::shortint::list_compression::private_key::NoiseSquashingCompressionPrivateKey;
use crate::shortint::noise_squashing::{
NoiseSquashingKey, NoiseSquashingPrivateKey, NoiseSquashingPrivateKeyView,
};
use crate::shortint::parameters::test_params::*;
use crate::shortint::parameters::*;
use rand::prelude::*;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
@@ -134,15 +134,15 @@ mod test {
#[test]
fn test_noise_squashing_compression_ci_run_filter() {
let keycache_entry =
KEY_CACHE.get_from_param(TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128);
KEY_CACHE.get_from_param(PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128);
let (cks, sks) = (keycache_entry.client_key(), keycache_entry.server_key());
let noise_squashing_private_key = NoiseSquashingPrivateKey::new(
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
);
let noise_squashing_key = NoiseSquashingKey::new(cks, &noise_squashing_private_key);
let compression_private_key = NoiseSquashingCompressionPrivateKey::new(
TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
);
let compression_key = noise_squashing_private_key
@@ -152,8 +152,7 @@ mod test {
let id_lut = sks.generate_lookup_table(|x| x);
let max_ct_count =
TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128
.lwe_per_glwe;
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128.lwe_per_glwe;
for ct_count in [0, 1, max_ct_count.0] {
// Generate random msgs

View File

@@ -2,7 +2,6 @@ use crate::shortint::keycache::KEY_CACHE;
use crate::shortint::noise_squashing::{
CompressedNoiseSquashingKey, NoiseSquashingKey, NoiseSquashingPrivateKey,
};
use crate::shortint::parameters::test_params::*;
use crate::shortint::parameters::*;
use rand::prelude::*;
use rand::thread_rng;
@@ -10,15 +9,15 @@ use rand::thread_rng;
#[test]
fn test_classic_noise_squashing_ci_run_filter() {
test_noise_squashing(
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
);
}
#[test]
fn test_multi_bit_noise_squashing_ci_run_filter() {
test_noise_squashing(
TEST_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
NOISE_SQUASHING_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
);
}
@@ -26,8 +25,8 @@ fn test_multi_bit_noise_squashing_ci_run_filter() {
#[test]
fn test_ks32_noise_squashing_ci_run_filter() {
test_noise_squashing(
TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
);
}

View File

@@ -342,13 +342,11 @@ pub(crate) mod test {
#[test]
fn oprf_compare_plain_ci_run_filter() {
use crate::shortint::gen_keys;
use crate::shortint::parameters::test_params::{
TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
};
use crate::shortint::parameters::test_params::TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
for params in [
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128),
ShortintParameterSet::from(PARAM_MESSAGE_2_CARRY_2_KS_PBS),
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128),
] {
let (ck, sk) = gen_keys(params);
@@ -449,15 +447,15 @@ pub(crate) mod test {
use crate::shortint::gen_keys;
use crate::shortint::parameters::test_params::{
TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128,
TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128,
TEST_PARAM_MULTI_BIT_GROUP_3_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128,
};
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
for params in [
ShortintParameterSet::from(
TEST_PARAM_MULTI_BIT_GROUP_3_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128,
),
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128),
ShortintParameterSet::from(PARAM_MESSAGE_2_CARRY_2_KS_PBS),
ShortintParameterSet::from(TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128),
] {
let (ck, sk) = gen_keys(params);

View File

@@ -1,4 +1,3 @@
use super::aliases::*;
use super::current_params::meta::cpu::*;
use super::current_params::meta::gpu::*;
use super::current_params::*;
@@ -86,7 +85,7 @@ pub const TEST_PARAM_MESSAGE_4_CARRY_4_COMPACT_PK_PBS_KS_GAUSSIAN_2M128: Classic
pub const TEST_PARAM_MESSAGE_1_CARRY_1_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
V1_6_PARAM_MESSAGE_1_CARRY_1_KS_PBS_GAUSSIAN_2M64;
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M64;
V1_6_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M64;
pub const TEST_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
V1_6_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M64;
pub const TEST_PARAM_MESSAGE_4_CARRY_4_KS_PBS_GAUSSIAN_2M64: ClassicPBSParameters =
@@ -110,7 +109,7 @@ pub const TEST_PARAM_MESSAGE_1_CARRY_7_KS_PBS_GAUSSIAN_2M128: ClassicPBSParamete
pub const TEST_PARAM_MESSAGE_2_CARRY_1_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
V1_6_PARAM_MESSAGE_2_CARRY_1_KS_PBS_GAUSSIAN_2M128;
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
V1_6_PARAM_MESSAGE_2_CARRY_2_KS_PBS_GAUSSIAN_2M128;
pub const TEST_PARAM_MESSAGE_2_CARRY_3_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
V1_6_PARAM_MESSAGE_2_CARRY_3_KS_PBS_GAUSSIAN_2M128;
pub const TEST_PARAM_MESSAGE_2_CARRY_4_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
@@ -124,7 +123,7 @@ pub const TEST_PARAM_MESSAGE_3_CARRY_1_KS_PBS_GAUSSIAN_2M128: ClassicPBSParamete
pub const TEST_PARAM_MESSAGE_3_CARRY_2_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
V1_6_PARAM_MESSAGE_3_CARRY_2_KS_PBS_GAUSSIAN_2M128;
pub const TEST_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
V1_6_PARAM_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M128;
pub const TEST_PARAM_MESSAGE_3_CARRY_4_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
V1_6_PARAM_MESSAGE_3_CARRY_4_KS_PBS_GAUSSIAN_2M128;
pub const TEST_PARAM_MESSAGE_3_CARRY_5_KS_PBS_GAUSSIAN_2M128: ClassicPBSParameters =
@@ -154,7 +153,7 @@ pub const TEST_PARAM_MESSAGE_2_CARRY_2_PBS_KS_GAUSSIAN_2M128: ClassicPBSParamete
// KS PBS TUniform
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128: ClassicPBSParameters =
PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
V1_6_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
// MultiBit
// CPU Gaussian
@@ -180,7 +179,8 @@ pub const TEST_PARAM_GPU_MULTI_BIT_GROUP_3_MESSAGE_3_CARRY_3_KS_PBS_GAUSSIAN_2M6
// GPU TUniform
pub const TEST_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
MultiBitPBSParameters = PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
MultiBitPBSParameters =
V1_6_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
// PKE ZK V1
pub const TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV1:
@@ -189,7 +189,7 @@ pub const TEST_PARAM_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV1:
// PKE ZK V2
pub const TEST_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
CompactPublicKeyEncryptionParameters = PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
CompactPublicKeyEncryptionParameters = V1_6_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
pub const TEST_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2:
CompactPublicKeyEncryptionParameters =
V1_6_PARAM_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV2;
@@ -202,13 +202,14 @@ pub const TEST_PARAM_KEYSWITCH_1_1_KS_PBS_TO_2_2_KS_PBS_GAUSSIAN_2M128:
ShortintKeySwitchingParameters = V1_6_PARAM_KEYSWITCH_1_1_KS_PBS_TO_2_2_KS_PBS_GAUSSIAN_2M128;
pub const TEST_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
ShortintKeySwitchingParameters = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
ShortintKeySwitchingParameters = V1_6_PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
pub const TEST_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
ShortintKeySwitchingParameters =
PARAM_KEYSWITCH_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
V1_6_PARAM_KEYSWITCH_PKE_TO_SMALL_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
pub const TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
ShortintKeySwitchingParameters = PARAM_KEYSWITCH_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
ShortintKeySwitchingParameters =
V1_6_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
// ZKV1
pub const TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV1:
ShortintKeySwitchingParameters =
@@ -216,21 +217,21 @@ pub const TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M12
// Compression
pub const TEST_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128: CompressionParameters =
COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
V1_6_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
pub const TEST_COMP_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
CompressionParameters =
COMP_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
V1_6_COMP_PARAM_GPU_MULTI_BIT_GROUP_4_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
// KS32 PBS AP
pub const TEST_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128: KeySwitch32PBSParameters =
PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
V1_6_PARAM_MESSAGE_2_CARRY_2_KS32_PBS_TUNIFORM_2M128;
pub const TEST_PARAM_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
NoiseSquashingCompressionParameters =
NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
V1_6_NOISE_SQUASHING_COMP_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
pub const TEST_PARAM_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128:
NoiseSquashingParameters = NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
NoiseSquashingParameters = V1_6_NOISE_SQUASHING_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
// Meta params
pub const TEST_META_PARAM_CPU_2_2_KS_PBS_PKE_TO_SMALL_ZKV2_TUNIFORM_2M128: MetaParameters =

View File

@@ -1,6 +1,6 @@
use crate::shortint::ciphertext::NoiseLevel;
use crate::shortint::keycache::KEY_CACHE;
use crate::shortint::parameters::test_params::TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
use crate::shortint::parameters::PARAM_MESSAGE_2_CARRY_2_KS_PBS;
use crate::shortint::{Ciphertext, MaxNoiseLevel, ServerKey};
fn test_ct_unary_op_noise_level_propagation(sk: &ServerKey, ct: &Ciphertext) {
@@ -319,7 +319,7 @@ fn test_ct_scalar_op_assign_noise_level_propagation(sk: &ServerKey, ct: &Ciphert
#[cfg(not(tarpaulin))] // This test is ignored in coverage, it takes around 4 hours to run otherwise.
#[test]
fn test_noise_level_propagation_ci_run_filter() {
let params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
let params = PARAM_MESSAGE_2_CARRY_2_KS_PBS;
let keys = KEY_CACHE.get_from_param(params);
let (ck, sk) = (keys.client_key(), keys.server_key());

View File

@@ -46,15 +46,6 @@ impl Named for CompactPkeProof {
const NAME: &'static str = "zk::CompactPkeProof";
}
impl CompactPkeProof {
pub fn to_le_bytes(&self) -> Vec<u8> {
match self {
Self::PkeV1(proof) => proof.to_le_bytes(),
Self::PkeV2(proof) => proof.to_le_bytes(),
}
}
}
#[derive(Copy, Clone)]
/// Used to specify the kind of proofs that are allowed to be checked by the verifier.
///

View File

@@ -6,10 +6,47 @@ mod traits;
pub use backend::Backend;
pub use bench_crate::BenchCrate;
use serde::Serialize;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::Path;
use std::{env, fmt};
pub use tfhe::hlapi::HlapiBench;
pub use tfhe::{HlIntegerOp, TfheLayer};
use crate::tfhe::hlapi::dex::Dex;
use crate::tfhe::hlapi::erc7984::Erc7984;
pub struct TestResult {
file: File,
}
impl TestResult {
pub fn new(file_name: &str) -> Self {
let file_path = Path::new(file_name);
Self::from_path(file_path)
}
pub fn from_path(path: &Path) -> Self {
if !path.exists() {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).expect("cannot create parent dirs");
}
File::create(path).expect("cannot create result file");
}
let file = OpenOptions::new()
.append(true)
.open(path)
.expect("cannot open result file");
Self { file }
}
pub fn write_result(&mut self, name: &str, value: usize) {
let line = format!("{name},{value}\n");
let error_message = format!("cannot write {name} result into file");
self.file.write_all(line.as_bytes()).expect(&error_message);
}
}
#[derive(Serialize)]
pub enum OperandType {
CipherText,
@@ -22,14 +59,36 @@ impl OperandType {
}
}
#[derive(Serialize)]
/// Benchmark type driven by the `__TFHE_RS_BENCH_TYPE` environment variable.
///
/// Only `Latency` and `Throughput` can come from the environment; `PbsCount`
/// is hard-coded at specific call sites.
#[derive(Clone, Copy, Serialize)]
pub enum BenchmarkType {
Latency,
Throughput,
}
/// The metric being recorded by a benchmark, used in [`BenchmarkSpec`].
#[derive(Clone, Copy, Serialize)]
pub enum BenchmarkMetric {
Latency,
Throughput,
PbsCount,
}
impl From<BenchmarkType> for BenchmarkMetric {
fn from(ct: BenchmarkType) -> Self {
match ct {
BenchmarkType::Latency => BenchmarkMetric::Latency,
BenchmarkType::Throughput => BenchmarkMetric::Throughput,
}
}
}
impl BenchmarkType {
pub fn from_env() -> Result<Self, String> {
/// Retrieves the benchmark type from the environment variable `__TFHE_RS_BENCH_TYPE`.
fn from_env() -> Result<Self, String> {
let raw_value = env::var("__TFHE_RS_BENCH_TYPE").unwrap_or("latency".to_string());
match raw_value.to_lowercase().as_str() {
"latency" => Ok(BenchmarkType::Latency),
@@ -39,6 +98,9 @@ impl BenchmarkType {
}
}
/// Retrieves the benchmark type from the environment variable `__TFHE_RS_BENCH_TYPE`.
///
/// Returns only `Latency` or `Throughput` — never `PbsCount`.
pub fn get_bench_type() -> &'static BenchmarkType {
use std::sync::OnceLock;
static BENCH_TYPE: OnceLock<BenchmarkType> = OnceLock::new();
@@ -48,7 +110,7 @@ pub fn get_bench_type() -> &'static BenchmarkType {
/// Enforces the naming convention for benchmark IDs.
///
/// ```text
/// {crate}::{layer}::{bench}::{op}(::{backend})?(::throughput)?::{param}(::scalar)?(::{type})?
/// {crate}::{layer}::{bench}::{op}(::{backend})?(::{benchmark_type})?::{param}(::scalar)?(::{type})?(::{num_elements}_elements)?
/// ```
///
/// `param_name` and `type_name` are kept as `&str` because their values
@@ -60,7 +122,8 @@ pub struct BenchmarkSpec<'a> {
pub param_name: &'a str,
pub operand_type: &'a OperandType,
pub type_name: Option<&'a str>,
pub bench_type: &'a BenchmarkType,
pub bench_type: BenchmarkMetric,
pub num_elements: Option<usize>,
}
impl<'a> BenchmarkSpec<'a> {
@@ -70,7 +133,8 @@ impl<'a> BenchmarkSpec<'a> {
param_name: &'a str,
operand_type: &'a OperandType,
type_name: Option<&'a str>,
bench_type: &'a BenchmarkType,
bench_type: impl Into<BenchmarkMetric>,
num_elements: Option<usize>,
) -> Self {
Self {
bench_crate,
@@ -78,16 +142,17 @@ impl<'a> BenchmarkSpec<'a> {
param_name,
operand_type,
type_name,
bench_type,
bench_type: bench_type.into(),
num_elements,
}
}
pub fn new_hlapi(
pub fn new_hlapi_ops(
hlapi_op: HlIntegerOp,
param_name: &'a str,
operand_type: &'a OperandType,
type_name: Option<&'a str>,
bench_type: &'a BenchmarkType,
bench_type: impl Into<BenchmarkMetric>,
backend: Backend,
) -> Self {
Self {
@@ -96,7 +161,47 @@ impl<'a> BenchmarkSpec<'a> {
param_name,
operand_type,
type_name,
bench_type,
bench_type: bench_type.into(),
num_elements: None,
}
}
pub fn new_hlapi_erc7984(
hlapi_erc7984_op: Erc7984,
param_name: &'a str,
operand_type: &'a OperandType,
type_name: Option<&'a str>,
bench_type: impl Into<BenchmarkMetric>,
backend: Backend,
num_elements: Option<usize>,
) -> Self {
Self {
bench_crate: BenchCrate::Tfhe(TfheLayer::Hlapi(HlapiBench::Erc7984(hlapi_erc7984_op))),
backend,
param_name,
operand_type,
type_name,
bench_type: bench_type.into(),
num_elements,
}
}
pub fn new_hlapi_dex(
hlapi_dex: Dex,
param_name: &'a str,
operand_type: &'a OperandType,
type_name: Option<&'a str>,
bench_type: impl Into<BenchmarkMetric>,
backend: Backend,
num_elements: Option<usize>,
) -> Self {
Self {
bench_crate: BenchCrate::Tfhe(TfheLayer::Hlapi(HlapiBench::Dex(hlapi_dex))),
backend,
param_name,
operand_type,
type_name,
bench_type: bench_type.into(),
num_elements,
}
}
}
@@ -107,8 +212,10 @@ impl fmt::Display for BenchmarkSpec<'_> {
if !matches!(self.backend, Backend::Cpu) {
write!(f, "::{}", self.backend)?;
}
if matches!(self.bench_type, BenchmarkType::Throughput) {
write!(f, "::throughput")?;
match self.bench_type {
BenchmarkMetric::Throughput => write!(f, "::throughput")?,
BenchmarkMetric::PbsCount => write!(f, "::pbs_count")?,
BenchmarkMetric::Latency => {}
}
write!(f, "::{}", self.param_name)?;
if self.operand_type.is_scalar() {
@@ -117,6 +224,9 @@ impl fmt::Display for BenchmarkSpec<'_> {
if let Some(type_name) = self.type_name {
write!(f, "::{type_name}")?;
}
if let Some(num_elements) = self.num_elements {
write!(f, "::{num_elements}_elements")?;
}
Ok(())
}
}
@@ -133,7 +243,8 @@ mod tests {
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
Some("FheUint64"),
&BenchmarkType::Latency,
BenchmarkMetric::Latency,
None,
);
assert_eq!(
spec.to_string(),
@@ -149,7 +260,8 @@ mod tests {
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
Some("FheUint128"),
&BenchmarkType::Latency,
BenchmarkMetric::Latency,
None,
);
assert_eq!(
spec.to_string(),
@@ -165,7 +277,8 @@ mod tests {
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
Some("FheUint64"),
&BenchmarkType::Throughput,
BenchmarkMetric::Throughput,
None,
);
assert_eq!(
spec.to_string(),
@@ -181,7 +294,8 @@ mod tests {
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::PlainText,
Some("FheUint64"),
&BenchmarkType::Latency,
BenchmarkMetric::Latency,
None,
);
assert_eq!(
spec.to_string(),
@@ -197,11 +311,164 @@ mod tests {
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
None,
&BenchmarkType::Latency,
BenchmarkMetric::Latency,
None,
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::ops::neg::PARAM_MESSAGE_2_CARRY_2"
);
}
#[test]
fn hlapi_erc7984_with_num_elements() {
use crate::tfhe::hlapi::erc7984::TransferFlavor;
let spec = BenchmarkSpec::new_hlapi_erc7984(
Erc7984::Transfer(TransferFlavor::Whitepaper),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
None,
BenchmarkMetric::Latency,
Backend::Cpu,
Some(10),
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::erc7984::transfer::whitepaper::PARAM_MESSAGE_2_CARRY_2::10_elements"
);
}
#[test]
fn hlapi_erc7984_without_num_elements() {
use crate::tfhe::hlapi::erc7984::TransferFlavor;
let spec = BenchmarkSpec::new_hlapi_erc7984(
Erc7984::Transfer(TransferFlavor::NoCmux),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
None,
BenchmarkMetric::Latency,
Backend::Cpu,
None,
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::erc7984::transfer::no_cmux::PARAM_MESSAGE_2_CARRY_2"
);
}
#[test]
fn hlapi_erc7984_num_elements_with_backend() {
use crate::tfhe::hlapi::erc7984::TransferFlavor;
let spec = BenchmarkSpec::new_hlapi_erc7984(
Erc7984::Transfer(TransferFlavor::Overflow),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
None,
BenchmarkMetric::Latency,
Backend::Cuda,
Some(5),
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::erc7984::transfer::overflow::cuda::PARAM_MESSAGE_2_CARRY_2::5_elements"
);
}
#[test]
fn hlapi_erc7984_num_elements_with_throughput() {
use crate::tfhe::hlapi::erc7984::TransferFlavor;
let spec = BenchmarkSpec::new_hlapi_erc7984(
Erc7984::Transfer(TransferFlavor::Safe),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
None,
BenchmarkMetric::Throughput,
Backend::Cpu,
Some(20),
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::erc7984::transfer::safe::throughput::PARAM_MESSAGE_2_CARRY_2::20_elements"
);
}
#[test]
fn hlapi_erc7984_with_pbs_count() {
use crate::tfhe::hlapi::erc7984::TransferFlavor;
let spec = BenchmarkSpec::new_hlapi_erc7984(
Erc7984::Transfer(TransferFlavor::Safe),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
None,
BenchmarkMetric::PbsCount,
Backend::Cpu,
None,
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::erc7984::transfer::safe::pbs_count::PARAM_MESSAGE_2_CARRY_2"
);
}
#[test]
fn hlapi_dex_swap_request_latency() {
use crate::tfhe::hlapi::dex::DexFlavor;
let spec = BenchmarkSpec::new_hlapi_dex(
Dex::SwapRequest(DexFlavor::Whitepaper),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
Some("FheUint64"),
BenchmarkMetric::Latency,
Backend::Cpu,
None,
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::dex::swap_request::whitepaper::PARAM_MESSAGE_2_CARRY_2::FheUint64"
);
}
#[test]
fn hlapi_dex_swap_claim_throughput_with_elements() {
use crate::tfhe::hlapi::dex::DexFlavor;
let spec = BenchmarkSpec::new_hlapi_dex(
Dex::SwapClaim(DexFlavor::NoCmux),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
Some("FheUint64"),
BenchmarkMetric::Throughput,
Backend::Cuda,
Some(10),
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::dex::swap_claim::no_cmux::cuda::throughput::PARAM_MESSAGE_2_CARRY_2::FheUint64::10_elements"
);
}
#[test]
fn hlapi_dex_with_pbs_count() {
use crate::tfhe::hlapi::dex::DexFlavor;
let spec = BenchmarkSpec::new_hlapi_dex(
Dex::SwapRequest(DexFlavor::Finalize),
"PARAM_MESSAGE_2_CARRY_2",
&OperandType::CipherText,
Some("FheUint64"),
BenchmarkMetric::PbsCount,
Backend::Cpu,
None,
);
assert_eq!(
spec.to_string(),
"tfhe::hlapi::dex::swap_request::finalize::pbs_count::PARAM_MESSAGE_2_CARRY_2::FheUint64"
);
}
}

View File

@@ -0,0 +1,37 @@
use core::fmt;
use strum::Display;
use crate::traits::SpecFmt;
/// DEX (decentralized exchange) benchmark operations for the HLAPI layer.
#[derive(Clone, Copy, Display)]
#[strum(serialize_all = "snake_case")]
pub enum Dex {
SwapRequest(DexFlavor),
SwapClaim(DexFlavor),
}
impl Dex {
fn op(&self) -> &dyn fmt::Display {
match self {
Dex::SwapRequest(op) => op,
Dex::SwapClaim(op) => op,
}
}
}
impl SpecFmt for Dex {
fn fmt_spec(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "::{}::{}", self, self.op())
}
}
#[derive(Clone, Copy, Display)]
#[strum(serialize_all = "snake_case")]
pub enum DexFlavor {
Whitepaper,
NoCmux,
Prepare,
Finalize,
}

View File

@@ -0,0 +1,37 @@
use core::fmt;
use strum::Display;
use crate::traits::SpecFmt;
/// ERC-7984 token transfer benchmark operations for the HLAPI layer.
#[derive(Clone, Copy, Display)]
#[strum(serialize_all = "snake_case")]
pub enum Erc7984 {
Transfer(TransferFlavor),
}
impl Erc7984 {
fn op(&self) -> &dyn fmt::Display {
match self {
Erc7984::Transfer(op) => op,
}
}
}
impl SpecFmt for Erc7984 {
fn fmt_spec(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "::{}::{}", self, self.op())
}
}
#[derive(Clone, Copy, Display)]
#[strum(serialize_all = "snake_case")]
pub enum TransferFlavor {
Whitepaper,
NoCmux,
Overflow,
Safe,
HpuOptim,
HpuSimd,
}

View File

@@ -1,3 +1,8 @@
pub mod dex;
pub mod erc7984;
use dex::Dex;
use erc7984::Erc7984;
use std::fmt;
use strum::Display;
@@ -17,18 +22,23 @@ pub use super::hl_integer_op::HlIntegerOp;
#[strum(serialize_all = "snake_case")]
pub enum HlapiBench {
Ops(HlIntegerOp),
Erc7984(Erc7984),
Dex(Dex),
}
impl HlapiBench {
fn op(&self) -> &dyn fmt::Display {
fn op(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
HlapiBench::Ops(op) => op,
HlapiBench::Ops(op) => write!(f, "::{op}"),
HlapiBench::Erc7984(op) => op.fmt_spec(f),
HlapiBench::Dex(op) => op.fmt_spec(f),
}
}
}
impl SpecFmt for HlapiBench {
fn fmt_spec(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "::{}::{}", self, self.op())
write!(f, "::{}", self)?;
self.op(f)
}
}

View File

@@ -1,5 +1,4 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use std::process::ExitCode;
@@ -376,15 +375,6 @@ impl Registry {
fn diff_enum(old_enum: &EnumSnapshot, new_enum: &EnumSnapshot, entries: &mut Vec<DiffEntry>) {
let name = &old_enum.enum_name;
let mut rename_map: HashMap<&str, &str> = HashMap::new();
for ov in &old_enum.variants {
if let Some(nv) = new_enum.variants.iter().find(|nv| nv.index == ov.index) {
if ov.inner_type_def_path != nv.inner_type_def_path {
rename_map.insert(&ov.inner_type_def_path, &nv.inner_type_def_path);
}
}
}
// Variant additions & modifications
for nv in &new_enum.variants {
match old_enum.variants.iter().find(|ov| ov.index == nv.index) {
@@ -406,11 +396,7 @@ impl Registry {
// Upgrade additions & modifications
for nu in &new_enum.upgrades {
match old_enum.upgrades.iter().find(|ou| {
let resolved_target = rename_map
.get(ou.target_def_path.as_str())
.copied()
.unwrap_or(ou.target_def_path.as_str());
ou.source_def_path == nu.source_def_path && resolved_target == nu.target_def_path
ou.source_def_path == nu.source_def_path && ou.target_def_path == nu.target_def_path
}) {
None => entries.push(DiffEntry::upgrade_added(name, nu)),
Some(ou) if ou.body_hash != nu.body_hash => {
@@ -423,11 +409,7 @@ impl Registry {
// Upgrade removals
for ou in &old_enum.upgrades {
if !new_enum.upgrades.iter().any(|nu| {
let resolved_target = rename_map
.get(ou.target_def_path.as_str())
.copied()
.unwrap_or(ou.target_def_path.as_str());
nu.source_def_path == ou.source_def_path && resolved_target == nu.target_def_path
nu.source_def_path == ou.source_def_path && nu.target_def_path == ou.target_def_path
}) {
entries.push(DiffEntry::upgrade_removed(name, ou));
}
@@ -694,110 +676,6 @@ mod tests {
assert_eq!(count_by_severity(&entries, Severity::Error), 0);
}
// ---- upgrade target rename (adding a new enum version) ----
/// Simulates adding V2 to an enum: Foo (at V1) becomes FooV1, new Foo is V2.
/// The existing upgrade FooV0 → Foo should be recognized as FooV0 → FooV1
/// (same upgrade, just renamed target) and NOT produce a false UpgradeRemoved + UpgradeAdded.
#[test]
fn no_false_positive_when_new_version_renames_target() {
// Before: V0(FooV0), V1(Foo) with upgrade FooV0 → Foo
let old = registry(vec![enum_snap(
"FooVersions",
vec![variant(0, "FooV0", "aaa"), variant(1, "Foo", "bbb")],
vec![upgrade("FooV0", "Foo", "uuu")],
)]);
// After: V0(FooV0), V1(FooV1), V2(Foo) with upgrades FooV0 → FooV1, FooV1 → Foo
let new = registry(vec![enum_snap(
"FooVersions",
vec![
variant(0, "FooV0", "aaa"),
variant(1, "FooV1", "bbb"), // same hash, just renamed
variant(2, "Foo", "ccc"),
],
vec![
upgrade("FooV0", "FooV1", "uuu"), // same body hash as the old FooV0 → Foo
upgrade("FooV1", "Foo", "vvv"), // genuinely new upgrade
],
)]);
let entries = old.diff(&new);
// Expected: new variant V2 + new upgrade FooV1→Foo = 2 neutral, 0 warnings, 0 errors
assert_eq!(count_by_severity(&entries, Severity::Neutral), 2);
assert_eq!(count_by_severity(&entries, Severity::Warning), 0);
assert_eq!(count_by_severity(&entries, Severity::Error), 0);
// Verify the 2 neutral entries are exactly: variant added + upgrade added
assert!(
entries
.iter()
.any(|e| matches!(e, DiffEntry::VersionsDispatchVariantAdded { index: 2, .. }))
);
assert!(entries.iter().any(|e| matches!(
e,
DiffEntry::UpgradeAdded {
source,
target,
..
} if source == "FooV1" && target == "Foo"
)));
}
/// Same scenario but the upgrade body also changed — should produce a hash-changed warning
/// instead of a false removed+added pair.
#[test]
fn renamed_target_with_changed_upgrade_body() {
let old = registry(vec![enum_snap(
"FooVersions",
vec![variant(0, "FooV0", "aaa"), variant(1, "Foo", "bbb")],
vec![upgrade("FooV0", "Foo", "uuu")],
)]);
let new = registry(vec![enum_snap(
"FooVersions",
vec![
variant(0, "FooV0", "aaa"),
variant(1, "FooV1", "bbb"),
variant(2, "Foo", "ccc"),
],
vec![
upgrade("FooV0", "FooV1", "CHANGED"), // same logical upgrade, body changed
upgrade("FooV1", "Foo", "vvv"),
],
)]);
let entries = old.diff(&new);
// The renamed upgrade has a changed body → 1 warning (UpgradeHashChanged)
// New variant + new upgrade → 2 neutral
assert_eq!(count_by_severity(&entries, Severity::Neutral), 2);
assert_eq!(count_by_severity(&entries, Severity::Warning), 1);
assert_eq!(count_by_severity(&entries, Severity::Error), 0);
assert!(
entries
.iter()
.any(|e| matches!(e, DiffEntry::UpgradeHashChanged { .. }))
);
}
/// When no rename happens (target name is stable), upgrades still match normally.
#[test]
fn no_rename_upgrades_still_match() {
let old = registry(vec![enum_snap(
"E",
vec![variant(0, "V0", "aaa"), variant(1, "V1", "bbb")],
vec![upgrade("V0", "V1", "uuu")],
)]);
let new = registry(vec![enum_snap(
"E",
vec![variant(0, "V0", "aaa"), variant(1, "V1", "bbb")],
vec![upgrade("V0", "V1", "uuu")],
)]);
let entries = old.diff(&new);
assert!(entries.is_empty());
}
#[test]
fn diff_full_flow_mixed_changes() {
let old = registry(vec![

View File

@@ -994,7 +994,6 @@ dependencies = [
"tfhe-csprng",
"tfhe-fft",
"tfhe-ntt",
"tfhe-safe-serialize",
"tfhe-versionable",
"tfhe-zk-pok",
]
@@ -1046,15 +1045,6 @@ dependencies = [
"pulp",
]
[[package]]
name = "tfhe-safe-serialize"
version = "0.1.0"
dependencies = [
"bincode",
"serde",
"tfhe-versionable",
]
[[package]]
name = "tfhe-versionable"
version = "0.7.0"
@@ -1083,13 +1073,11 @@ dependencies = [
"ark-ff",
"ark-poly",
"getrandom",
"itertools 0.14.0",
"num-bigint",
"rand",
"rayon",
"serde",
"sha3",
"tfhe-safe-serialize",
"tfhe-versionable",
"zeroize",
]