Concrete v2.6: Approximate PBS, Input Compression, Extended Composable Functions, Speed Improvements

April 8, 2024
Quentin Bourgerie

Concrete v2.6 introduces the approximate programmable bootstrapping (PBS), input compression, enhanced function composition and faster simulations, ternary-if, Relu, and Sign functions. These improvements bring significant value to users by enhancing the performance, efficiency, and functionality of Concrete.

Approximate PBS

In Concrete Python, non-linear operations are transformed into table-lookup (TLU) and then performed with PBS in the TFHE framework.

PBS is the most expensive operation in TFHE. The computational complexity of PBS depends on the size of the crypto parameters, and the size of these parameters grows with the number of bits of encrypted messages to be bootstrapped. As the message size increases, the computational cost of bootstrapping grows exponentially. To mitigate this impact, round and truncate operators were introduced in previous releases. Applying these operators before bootstrapping can reduce the message bit width by ignoring the information in the least significant bits (LSB) of the messages, thus dramatically increasing the speed of TLU.

Concrete v2.6 introduces a much more aggressive mode for rounding that speeds up TLUs 2 to 3 times faster, at the cost of an inexact rounding. This feature can greatly improve the performance of applications that are tolerant to inexact rounding. For example, it can be highly beneficial in Concrete ML for deep learning tasks.

For more details, please check our documentation on approximate rounding.

Input compression

The previous Concrete v2.5 introduced compression that reduces the size of evaluation keys by a factor of 4. In this release, Concrete v2.6 enhances compression capabilities with the new input ciphertext compression to further optimize bandwidth and disk space utilization. The input ciphertext compression uses seeded ciphertexts under the hood. While the compression factor depends on various factors, the compressed input ciphertexts are typically hundreds to thousands of times smaller than their uncompressed versions.

Enabling input ciphertext compression is just a matter of setting the option, as shown in the code sample below:

from concrete import fhe


@fhe.compiler({"x": "encrypted"})
def f(x):
  return x // 2


circuit = f.compile(fhe.inputset(fhe.tensor[fhe.uint8, 1000]),
                       compress_input_ciphertexts=True)

Extended function composability

In Concrete v2.5, self-composable functions allow you to use the encrypted output of a function as one of its inputs. That's pretty cool, but there are limitations. In this release, we advance further on the function composability and introduce the beta version of function set composition, called module - you can define a set of functions in your FHE modules and call them in any order that you want.

This feature extends more possibilities of Concrete by enabling developers to program any non-encrypted control flow in pure Python, with the different parties working over encrypted data.

from concrete import fhe


@fhe.module()
class MyModule:
   @fhe.function({"x": "encrypted"})
   def inc(x):
       return x + 1 % 20


   @fhe.function({"x": "encrypted"})
   def dec(x):
       return x - 1 % 20
  
inputset = list(range(20))
my_module = MyModule.compile(
   {"inc": inputset, "dec": inputset},
)


x = 5
x_enc = my_module.inc.encrypt(x)
x_inc_enc = my_module.inc.run(x_enc)
x_inc = my_module.inc.decrypt(x_inc_enc)
assert x_inc == 6


x_inc_dec_enc = my_module.dec.run(x_inc_enc)
x_inc_dec = my_module.dec.decrypt(x_inc_dec_enc)
assert x_inc_dec == 5


for _ in range(10):
   x_enc = my_module.inc.run(x_enc)
x_dec = my_module.inc.decrypt(x_enc)
assert x_dec == 15

⚠️ Be aware that this feature is currently in beta. The optimization of cryptographic parameters is somewhat restricted, potentially resulting in compilation failures or slower execution times. Additionally, there may be the possibility of API breaks.

For the next release, the team will work on improved optimization, finer specification of function relationships, and a stable API. Your feedback and suggestions are very welcomed, they will help us shape the future of Concrete. Click here to participate in our developer survey.

Faster simulation

With simulation, developers can fine-tune their functions or models quickly during the development phase without the computational constraints of FHE. For instance, Concrete simulation is used a lot in Concrete ML. In Concrete v2.6, the Zama team has improved the simulation speed to be up to 100x faster. There are no changes required in the API or usage from the users’ side, you can already take advantage of faster simulation without anything in your code.  If you haven't already used the simulation, it’s time to have a look at the documentation and give it a try.

Faster operators

Finally, we have significantly improved the speed of these functions

  • If-then-else operation: to typically code [.c-inline-code]y = condition ? value_if_true : value_if_false[.c-inline-code] C-operator, which can also be defined as  [.c-inline-code]y = value_if_false + condition * (value_if_true - value_if_false)[.c-inline-code] with a boolean condition.
  • Relu: we have accelerated the ML Relu activation, which is the most used activation function [.c-inline-code]Relu(x) = max(0, x)[.c-inline-code]
  • Sign: we have accelerated the Sign function, [.c-inline-code]Sign(x) = 1 if x>=0 else -1[.c-inline-code]. 

Furthermore, Concrete v2.6 includes several additional minor improvements that you can find in GitHub or the release note. These improvements don’t require any change in the API, so we encourage you to test our latest releases and enjoy the benefits of these improvements without any additional effort.

Additional links

Read more related posts