Common tips
This document introduces several common techniques for optimizing code to fit Fully Homomorphic Encryption (FHE) constraints. The examples provided demonstrate various workarounds and performance optimizations that you can implement while working with the Concrete library.
Retrieving a value within an encrypted array with an encrypted index
This example demonstrates how to retrieve a value from an array using an encrypted index. The method creates a "selection" array filled with 0s except for the requested index, which will be 1. It then sums the products of all array values with this selection array:
import numpy as np
from concrete import fhe
@fhe.compiler({"array": "encrypted", "index": "encrypted"})
def indexed_value(array, index):
all_indices = np.arange(array.size)
index_selection = index == all_indices
selection_and_zeros = array * index_selection
selection = np.sum(selection_and_zeros)
return selection
inputset = [(np.random.randint(0, 16, size=5), np.random.randint(0, 5)) for _ in range(50)]
circuit = indexed_value.compile(inputset)
array = np.random.randint(0, 16, size=5)
index = np.random.randint(0, 5)
assert circuit.encrypt_run_decrypt(array, index) == array[index]Filter an array with comparison (>)
This example filters an encrypted array with an encrypted condition, in this case a greater than comparison with an encrypted value. It packs all values with a selection bit that results from the comparison, allowing the unpacking of only the filtered values:
Matrix Row/Col means
This example introduces a key concept when using Concrete: maximizing parallelization. Instead of sequentially summing all values to compute a mean, the values are split into sub-groups, and the mean of these sub-group means is computed:
Last updated
Was this helpful?