Concrete v2.0.0: Improving performance and developer experience

July 25, 2023
Quentin Bourgerie

The release of Concrete v2.0.0 brings significant enhancements and new features, along with a few minor yet essential changes. These modifications served as the rationale for upgrading the major version number.

More accurate simulation

First, a more precise simulation is introduced. This tool facilitates simulating actual Fully Homomorphic Encryption (FHE) execution to speed up the development cycle. The aim is to avoid bearing the cost of actual FHE execution during the development phase. The simulation in v1.0.0 was at the Python level, where some further transformations were unknown, making it less accurate than desired.

To resolve this, a completely new simulation has been designed which essentially follows the entire compilation pipeline and produces binary code that matches what the actual FHE compilation would yield. The only distinction is that the code operates on noisy plaintext instead of actual Learning With Errors (LWE) ciphertext, making the simulation not only accurate but significantly faster than the actual FHE evaluation. Moreover, thanks to the compilation, the majority of use cases will execute more quickly with the new simulation than the old one, and even faster than evaluation in the clear.

Regarding the API, nothing has changed – the call to the simulate function will lazily compile to the simulation backend and evaluate the compiled function.

from concrete import fhe

@fhe.compiler({"x": "encrypted", "y": "encrypted"})
def f(x, y):
    return (x + y) ** 2

inputset = [(0, 2), (3, 4), (1, 5), (6, 6), (7, 0)]
circuit = f.compile(inputset)

assert circuit.simulate(1, 2) == f(1, 2)

Note: This first version of the simulation backend does not include all the same features as the actual FHE computation, especially the simulation of pbs of large integers; this support will come soon.

Separate arguments

In Concrete v1.0.0, the parameters of the FHE function needed to be bundled into a [.c-inline-code]PublicArguments[.c-inline-code] object, and the outcome was delivered in a [.c-inline-code]PublicResul[.c-inline-code]t object. This arrangement had a significant drawback: all arguments had to be encrypted simultaneously, which was not particularly convenient. However, with Concrete v2.0.0, there is now the ability to encrypt different arguments individually and reuse them in multiple runs.

from concrete import fhe

@fhe.compiler({"x": "encrypted", "y": "encrypted"})
def f(x, y):
    return (x + y) ** 2

inputset = [(0, 2), (3, 4), (1, 5), (6, 6), (7, 0)]
circuit = f.compile(inputset)

# Encrypt the first argument
arg1, _ = circuit.client.encrypt(1, None)

# Encrypt the second argument
_, arg2 = circuit.client.encrypt(None, 2)

# Evaluate
result = circuit.server.run(arg1, arg2, evaluation_keys=circuit.client.evaluation_keys)
assert circuit.client.decrypt(result) == f(1, 2)

# Encrypt the second argument with a different value
_, another_arg2 = circuit.client.encrypt(None, 4)

# Evaluate
another_result = circuit.server.run(arg1, another_arg2, evaluation_keys=circuit.client.evaluation_keys)
assert circuit.client.decrypt(another_result) == f(1, 4)

For those familiar with Concrete v1.0.0, a slight modification is evident: the evaluation keys can no longer be a positional argument and must now be designated as a keyword argument.

This change has been implemented because the number of arguments is no longer restricted to just two. Therefore, Python now requires evaluation keys to be specified as a keyword argument.

Multi parameters optimization

One of the notable enhancements in Concrete v2.0.0 is the introduction of multi-parameter optimization. What does this entail?

During the compilation of a Python function, Concrete Python traces the computation, assessing the minimum bit width required for each component of the evaluation. Given that adding an extra bit to an FHE evaluation comes with considerable cost and a significant increase in execution time, this optimization is crucial. The predecessor of Concrete v2.0.0 offered mono-parameter optimization, assigning the same set of parameters to all components of the evaluation, which corresponded to the component with the maximum bitwidth. In contrast, the multi-parameter optimization in v2.0.0 assigns a tailored set of parameters to each component. This feature considerably reduces the execution time of the FHE evaluation across various use cases.

This feature is in beta in the v2.0.0 release and will be activated by default on future releases. There are two compilation options exposed in order to toggle this optimization, the [.c-inline-code]single_precison[.c-inline-code] and the [.c-inline-code]parameter_selection_strategy[.c-inline-code].

from concrete import fhe

@fhe.compiler({"x": "encrypted", "y": "encrypted"})
def f(x, y):
...

inputset = [(0, 2), (3, 4), (1, 5), (6, 6), (7, 0)]
circuit = f.compile(
...,
single_precision=False,
parameter_selection_strategy=fhe.ParameterSelectionStrategy.MULTI,
)

Round: A new operator for faster PBS

As described earlier, adding a bit increases the complexity of the FHE evaluation. Therefore, in addition to multi-parameter support, Concrete v2.0.0 introduces a rounding operator. This operator enables you to retain only the most significant bits of an encrypted value, effectively reducing the bit count in sections of your computation where the information in the least significant bits can be disregarded. This operator assists in optimizing the performance of your function by allowing more precise adjustments: read more about it in the documentation.

A compelling illustration of the effective application of the rounding operator can be seen in Concrete ML's use on the CIFAR case study, which resulted in a 20x speedup.

Progress bar and Ctrl-C

Along with Concrete v2.0.0, two user-friendly features are introduced to enhance the developer experience: a progress bar and support for Ctrl-C to terminate the program. The progress bar helps you gauge the remaining time for the computation. And with the help of tags, you can track exactly where you are within your FHE function. A comprehensive tutorial can be found in the documentation.

Try it out!

Concrete v2.0.0 arrives with refreshed, fine-tuned documentation, this time with an emphasis on the internal workings of Concrete, not just the Python frontend. It also includes bug fixes from Concrete v1.0.0 that were either detected in-house or reported by you, our users, which we thank.

Have fun engaging with this new release of Concrete. Feedback is always welcome, as it helps drive the ongoing realization of Fully Homomorphic Encryption.

Additional links

Read more related posts