diff --git a/tfhe/docs/fundamentals/serialization.md b/tfhe/docs/fundamentals/serialization.md index aaa319badb..6f3b5486d6 100644 --- a/tfhe/docs/fundamentals/serialization.md +++ b/tfhe/docs/fundamentals/serialization.md @@ -24,7 +24,7 @@ fn main() { let mut buffer = vec![]; - // The last argument is the max allowed size for the serialized buffer + // The last argument is the max allowed size for the serialized buffer safe_serialize(&server_key, &mut buffer, 1 << 30).unwrap(); let _server_key_deser: ServerKey = diff --git a/tfhe/docs/getting_started/benchmarks/cpu_benchmarks.md b/tfhe/docs/getting_started/benchmarks/cpu_benchmarks.md index 84cf4c70ca..0b675c28a9 100644 --- a/tfhe/docs/getting_started/benchmarks/cpu_benchmarks.md +++ b/tfhe/docs/getting_started/benchmarks/cpu_benchmarks.md @@ -14,11 +14,11 @@ The following tables benchmark the execution time of some operation sets using ` The next table shows the operation timings on CPU when all inputs are encrypted -{% embed url="https://docs.google.com/spreadsheets/d/1Z2NZvWEkDnbHPYE4Su0Oh2Zz1VBnT9dWbo3E29-LcDg/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1b_-72ArnSdaqfr-gJOnMmVdcBokYZohnylO4LUj2PMw/edit?usp=sharing" %} The next table shows the operation timings on CPU when the left input is encrypted and the right is a clear scalar of the same size: -{% embed url="https://docs.google.com/spreadsheets/d/1NGPnuBhRasES9Ghaij4ixJJTpXVMqDzbqMniX-qIMGc/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1m3tjCi_2GSIHop2zZLAtVbhdDn5wqTGd2lOA3CcJe-U/edit?usp=sharing" %} All timings are based on parallelized Radix-based integer operations where each block is encrypted using the default parameters `PARAM_MESSAGE_2_CARRY_2_KS_PBS`. To ensure predictable timings, we perform operations in the `default` mode, which ensures that the input and output encoding are similar (i.e., the carries are always emptied). @@ -28,7 +28,9 @@ You can minimize operational costs by selecting from 'unchecked', 'checked', or The next table shows the execution time of a keyswitch followed by a programmable bootstrapping depending on the precision of the input message. The associated parameter set is given. The configuration is Concrete FFT + AVX-512. -{% embed url="https://docs.google.com/spreadsheets/d/1OdZrsk0dHTWSLLvstkpiv0u5G5tE0mCqItTb7WixGdg/edit?usp=sharing" %} +Note that these benchmarks use Gaussian parameters. + +{% embed url="https://docs.google.com/spreadsheets/d/1o6MWpbzbYhDs3Pnoq-2hlNEgO9G8wGR5niW-OOZ6c_4/edit?usp=sharing" %} ## Reproducing TFHE-rs benchmarks diff --git a/tfhe/docs/getting_started/benchmarks/gpu_benchmarks.md b/tfhe/docs/getting_started/benchmarks/gpu_benchmarks.md index a271129bec..4674a47f3e 100644 --- a/tfhe/docs/getting_started/benchmarks/gpu_benchmarks.md +++ b/tfhe/docs/getting_started/benchmarks/gpu_benchmarks.md @@ -8,26 +8,28 @@ All GPU benchmarks presented here were obtained on H100 GPUs, and rely on the mu Below come the results for the execution on a single H100. The following table shows the performance when the inputs of the benchmarked operation are encrypted: -{% embed url="https://docs.google.com/spreadsheets/d/1dhNYXm7oY0l2qjX3dNpSZKjIBJElkEZtPDIWHZ4FA_A/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1xGWykMa8fZ7RWUjkCl-52FJ-BNge8cB-5CSHrVZ6XRo/edit?usp=sharing" %} The following table shows the performance when the left input of the benchmarked operation is encrypted and the other is a clear scalar of the same size: -{% embed url="https://docs.google.com/spreadsheets/d/1wtnFnOwHrSOvfTWluUEaDoTULyveseVl1ZsYo3AOFKk/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1MZfE9c-cQw3yAP55tu0i8uLl4lTAiH9zW3gRFp0ve7s/edit?usp=sharing" %} ## 2xH100 Below come the results for the execution on two H100's. The following table shows the performance when the inputs of the benchmarked operation are encrypted: -{% embed url="https://docs.google.com/spreadsheets/d/1_2AUeu3ua8_PXxMfeJCh-pp6b9e529PGVEYUuZRAThg/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1bcL0wgFk-cfR4asGSCWDFt7JaqDYJT-l4pH58A-yBkc/edit?usp=sharing" %} The following table shows the performance when the left input of the benchmarked operation is encrypted and the other is a clear scalar of the same size: -{% embed url="https://docs.google.com/spreadsheets/d/1nLPt_m1MbkSdhMop0iKDnSN_c605l_JdMpK5JC90N_Q/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1_8VIoStixns22lQq_RBSjVm-0iFHjJpntQTrvEHZpSg/edit?usp=sharing" %} ## Programmable bootstrapping The next table shows the execution time of a keyswitch followed by a programmable bootstrapping depending on the precision of the input message. The associated parameter set is given. -{% embed url="https://docs.google.com/spreadsheets/d/11JfbPxJ8XMMfob4AZIWhDSglTO9X_YX8R7dNQK73uuk/edit?usp=sharing" %} +Note that these benchmarks use Gaussian parameters. + +{% embed url="https://docs.google.com/spreadsheets/d/1KhElQ7sIsShUSVQw5bKFoP-x5BgMaWh1pZtrVAdC3T4/edit?usp=sharing" %} diff --git a/tfhe/docs/getting_started/benchmarks/summary.md b/tfhe/docs/getting_started/benchmarks/summary.md index d980f7ee92..abd3919b2f 100644 --- a/tfhe/docs/getting_started/benchmarks/summary.md +++ b/tfhe/docs/getting_started/benchmarks/summary.md @@ -2,6 +2,8 @@ This document summarizes the timings of some homomorphic operations over 64-bit encrypted integers, depending on the hardware. More details are given for [the CPU](cpu\_benchmarks.md), [the GPU](gpu\_benchmarks.md), or [zeros-knowledge proofs](zk\_proof\_benchmarks.md). +The cryptographic parameters used for benchmarking follow a tweaked uniform (TUniform) noise distribution instead of a Gaussian. The main advantage of this distribution is to be bounded, whereas the usual Gaussian one is not. In some practical cases, this can simplify the use of homomorphic computation. See the [noise section](../security\_and\_cryptography.md#noise) of the Security and cryptography documentation page for more information on the noise distributions. + You can get the parameters used for benchmarks by cloning the repository and checking out the commit you want to use (starting with the v0.11.0 release) and run the following make command: ```console @@ -10,4 +12,4 @@ make print_doc_bench_parameters ### Operation time (ms) over FheUint 64 -{% embed url="https://docs.google.com/spreadsheets/d/1ZbgsKnFH8eKrFjy9khFeaLYnUhbSV8Xu4H6rwulo0o8/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1OMdGSakEUbIFSEQKhAinTolJjvmPBbafi3DEe3UfzsQ/edit?usp=sharing" %} diff --git a/tfhe/docs/getting_started/benchmarks/zk_proof_benchmarks.md b/tfhe/docs/getting_started/benchmarks/zk_proof_benchmarks.md index 2cb3a298b6..d6836b20e3 100644 --- a/tfhe/docs/getting_started/benchmarks/zk_proof_benchmarks.md +++ b/tfhe/docs/getting_started/benchmarks/zk_proof_benchmarks.md @@ -4,4 +4,4 @@ This document details the performance benchmarks of [zero-knowledge proofs](../. Benchmarks for the zero-knowledge proofs have been run on a `m6i.4xlarge` with 16 cores to simulate an usual client configuration. The verification are done on a `hpc7a.96xlarge` AWS instances to mimic a powerful server. -{% embed url="https://docs.google.com/spreadsheets/d/1llCYHCz2CyLdTwXkiqhjVzJLzxW_RqdjHxmk72m1jm4/edit?usp=sharing" %} +{% embed url="https://docs.google.com/spreadsheets/d/1x12I7Tkdx63Q6sNllygg6urSd5KC1sj1wj4L9jWiET4/edit?usp=sharing" %} diff --git a/tfhe/docs/getting_started/operations.md b/tfhe/docs/getting_started/operations.md index 8c396c8206..4f822fe797 100644 --- a/tfhe/docs/getting_started/operations.md +++ b/tfhe/docs/getting_started/operations.md @@ -274,39 +274,39 @@ use tfhe::prelude::*; use tfhe::{generate_keys, set_server_key, ConfigBuilder, FheInt32}; fn main() -> Result<(), Box> { - // Basic configuration to use homomorphic integers + // Basic configuration to use homomorphic integers let config = ConfigBuilder::default().build(); - // Key generation - let (client_key, server_keys) = generate_keys(config); - - let clear_a = 32i32; - let clear_b = -45i32; - - // Encrypting the input data using the (private) client_key - // FheInt32: Encrypted equivalent to i32 - let encrypted_a = FheInt32::try_encrypt(clear_a, &client_key)?; - let encrypted_b = FheInt32::try_encrypt(clear_b, &client_key)?; - - // On the server side: - set_server_key(server_keys); - - // Clear equivalent computations: 32 > -45 - let encrypted_comp = &encrypted_a.gt(&encrypted_b); - let clear_res = encrypted_comp.decrypt(&client_key); - assert_eq!(clear_res, clear_a > clear_b); - - // `encrypted_comp` is a FheBool, thus it encrypts a boolean value. + // Key generation + let (client_key, server_keys) = generate_keys(config); + + let clear_a = 32i32; + let clear_b = -45i32; + + // Encrypting the input data using the (private) client_key + // FheInt32: Encrypted equivalent to i32 + let encrypted_a = FheInt32::try_encrypt(clear_a, &client_key)?; + let encrypted_b = FheInt32::try_encrypt(clear_b, &client_key)?; + + // On the server side: + set_server_key(server_keys); + + // Clear equivalent computations: 32 > -45 + let encrypted_comp = &encrypted_a.gt(&encrypted_b); + let clear_res = encrypted_comp.decrypt(&client_key); + assert_eq!(clear_res, clear_a > clear_b); + + // `encrypted_comp` is a FheBool, thus it encrypts a boolean value. // This acts as a condition on which the - // `select` function can be applied on. - // Clear equivalent computations: - // if 32 > -45 {result = 32} else {result = -45} - let encrypted_res = &encrypted_comp.select(&encrypted_a, &encrypted_b); - - let clear_res: i32 = encrypted_res.decrypt(&client_key); - assert_eq!(clear_res, clear_a); - - Ok(()) + // `select` function can be applied on. + // Clear equivalent computations: + // if 32 > -45 {result = 32} else {result = -45} + let encrypted_res = &encrypted_comp.select(&encrypted_a, &encrypted_b); + + let clear_res: i32 = encrypted_res.decrypt(&client_key); + assert_eq!(clear_res, clear_a); + + Ok(()) } ``` diff --git a/tfhe/docs/getting_started/security_and_cryptography.md b/tfhe/docs/getting_started/security_and_cryptography.md index e8538f804d..0277060bed 100644 --- a/tfhe/docs/getting_started/security_and_cryptography.md +++ b/tfhe/docs/getting_started/security_and_cryptography.md @@ -63,7 +63,9 @@ The following sections explain the concept of noise and padding in ciphertexts. To ensure security, LWE requires random noise to be added to the message during encryption. -TFHE scheme draws this random noise from a Centered Normal Distribution with a standard deviation parameter. The choice of standard deviation impacts the security level: increasing the standard deviation enhances security while keeping other factors constant. +TFHE scheme draws this random noise either from: +- A Centered Normal Distribution with a standard deviation parameter. The choice of standard deviation impacts the security level: increasing the standard deviation enhances security while keeping other factors constant. +- A Tweaked Uniform (TUniform) Distribution with a bound parameter $2^b$ defined as follows: any value in the interval $(−2^b, ... , 2^b)$ is selected with probability $1/2^{b+1}$, with the two end points $−2^b$ and $2^b$ being selected with probability $1/2^{b+2}$. The main advantage of this distribution is to be bounded, whereas the usual Central Normal Distribution one is not. In some practical cases, this can simplify the use of homomorphic computation. The choice of the bound impacts the security level: increasing the bound enhances security while keeping other factors constant. **TFHE-rs** encodes the noise in the least significant bits of each plaintext. Each leveled computation increases the value of the noise. If too many computations are performed, the noise will eventually overflow into the message bits and lead to an incorrect result. diff --git a/tfhe/docs/guides/overflow_operations.md b/tfhe/docs/guides/overflow_operations.md index 2a772185bd..4e3bf61ede 100644 --- a/tfhe/docs/guides/overflow_operations.md +++ b/tfhe/docs/guides/overflow_operations.md @@ -35,8 +35,8 @@ let (result, overflowed) = (&a).overflowing_add(&b); let result: u16 = result.decrypt(&client_key); assert_eq!(result, u16::MAX.wrapping_add(1u16)); assert_eq!( - overflowed.decrypt(&client_key), - u16::MAX.overflowing_add(1u16).1 + overflowed.decrypt(&client_key), + u16::MAX.overflowing_add(1u16).1 ); assert!(overflowed.decrypt(&client_key)); ```