GPU acceleration
This guide explains how to update your existing program to leverage GPU acceleration, or to start a new program using GPU.
TFHE-rs now supports a GPU backend with CUDA implementation, enabling integer arithmetic operations on encrypted data.
Prerequisites
Cuda version >= 10
Compute Capability >= 3.0
cmake >= 3.24
libclang, to match Rust bingen requirements >= 9.0
Rust version - check this page
Importing to your project
To use the TFHE-rs GPU backend in your project, add the following dependency in your Cargo.toml
.
tfhe = { version = "~1.1.3", features = ["boolean", "shortint", "integer", "gpu"] }
For optimal performance when using TFHE-rs, run your code in release mode with the --release
flag.
Supported platforms
TFHE-rs GPU backend is supported on Linux (x86, aarch64).
Linux
Supported
Supported*
macOS
Unsupported
Unsupported*
Windows
Unsupported
Unsupported
A first example
Configuring and creating keys.
Comparing to the CPU example, GPU set up differs in the key creation, as detailed here
Here is a full example (combining the client and server parts):
use tfhe::{ConfigBuilder, set_server_key, FheUint8, ClientKey, CompressedServerKey};
use tfhe::prelude::*;
fn main() {
let config = ConfigBuilder::default().build();
let client_key= ClientKey::generate(config);
let compressed_server_key = CompressedServerKey::new(&client_key);
let gpu_key = compressed_server_key.decompress_to_gpu();
let clear_a = 27u8;
let clear_b = 128u8;
let a = FheUint8::encrypt(clear_a, &client_key);
let b = FheUint8::encrypt(clear_b, &client_key);
//Server-side
set_server_key(gpu_key);
let result = a + b;
//Client-side
let decrypted_result: u8 = result.decrypt(&client_key);
let clear_result = clear_a + clear_b;
assert_eq!(decrypted_result, clear_result);
}
Beware that when the GPU feature is activated, when calling: let config = ConfigBuilder::default().build();
, the cryptographic parameters differ from the CPU ones, used when the GPU feature is not activated. Indeed, TFHE-rs uses dedicated parameters for the GPU in order to achieve better performance.
Setting the keys
The configuration of the key is different from the CPU. More precisely, if both client and server keys are still generated by the client (which is assumed to run on a CPU), the server key has then to be decompressed by the server to be converted into the right format. To do so, the server should run this function: decompressed_to_gpu()
.
Once decompressed, the operations between CPU and GPU are identical.
Encryption
On the client-side, the method to encrypt the data is exactly the same than the CPU one, as shown in the following example:
let clear_a = 27u8;
let clear_b = 128u8;
let a = FheUint8::encrypt(clear_a, &client_key);
let b = FheUint8::encrypt(clear_b, &client_key);
Computation
The server first need to set up its keys with set_server_key(gpu_key)
.
Then, homomorphic computations are performed using the same approach as the CPU operations.
//Server-side
set_server_key(gpu_key);
let result = a + b;
//Client-side
let decrypted_result: u8 = result.decrypt(&client_key);
let clear_result = clear_a + clear_b;
assert_eq!(decrypted_result, clear_result);
Decryption
Finally, the client decrypts the results using:
let decrypted_result: u8 = result.decrypt(&client_key);
Last updated
Was this helpful?