Skip to content

Commit

Permalink
Public Dev Sync-4 November 2020
Browse files Browse the repository at this point in the history
HElib 1.2.0, November 2020
=========================
(tagged as v1.2.0)

October-November 2020
---------------------
* Mitigation for potential CKKS vulnerability.
* Additional API changes for parameters to the CKKS encoding functions.
* New infrastructure for benchmarks
* Updated ClonedPtr
* Additional Ctxt tests
* Bug Fixes:

Co-Authored-by: Flavio Bergamaschi [email protected]
Co-authored-by: Jack Crawford [email protected]
Co-Authored-by: Shai Halevi [email protected]
Co-authored-by: Hamish Hunt [email protected]
Co-authored-by: Victor Shoup [email protected]
Co-authored-by: Enrico Steffinlongo [email protected]
  • Loading branch information
faberga authored Nov 25, 2020
2 parents c5a3ae5 + 9cec8a2 commit f8230cd
Show file tree
Hide file tree
Showing 53 changed files with 2,522 additions and 589 deletions.
13 changes: 13 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
HElib 1.2.0, November 2020
=========================
(tagged as v1.2.0)

October-November 2020
---------------------
* Mitigation for potential CKKS vulnerability.
* Additional API changes for parameters to the CKKS encoding functions.
* New infrastructure for benchmarks
* Updated ClonedPtr
* Additional Ctxt tests
* Bug Fixes

HElib 1.1.0, October 2020
=========================
(tagged as v1.1.0)
Expand Down
6 changes: 3 additions & 3 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Building and installing HElib

The HElib build, install, and regression tests suite have been built and tested
on Ubuntu 18.04, Ubuntu 20.04, Fedora 31, Fedora 32, CentOS 7.7, CentOS 8.1,
and macOS Mojave 10.14.
on Ubuntu 18.04, Ubuntu 20.04, Fedora 32, Fedora 33, CentOS 7.8, CentOS 8.2,
macOS Mojave >=10.14.6, and macOS Catalina >=10.15.7.

There are two different ways to build and install HElib. The first one will
automatically download and build the GMP and NTL dependencies and pack the
Expand All @@ -23,7 +23,7 @@ dependencies to be installed by you and available in the system.
- cmake >= 3.10.2

**macOS environment:**
- Apple clang >= 11.0.0 (available with Xcode >= 11.0)
- Apple clang >= 11.0.0 (available with the latest Xcode for the tested versions of macOS)
- Xcode Command Line Tools (can be installed with the command `xcode-select
--install` in a teminal)
- cmake >= 3.17.3 (available from [CMake](https://cmake.org/) or [MacPorts
Expand Down
35 changes: 31 additions & 4 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})

# Will be compiled into single executable
option(SINGLE_EXEC "Compile into single excutable (ON/OFF)" OFF)
if(SINGLE_EXEC)
message(STATUS "Single executable activated.")
endif()

# Setting up RelWithDebInfo as default CMAKE_BUILD_TYPE
if (NOT CMAKE_BUILD_TYPE)
Expand All @@ -42,9 +47,31 @@ endif (NOT CMAKE_BUILD_TYPE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "RelWithDebInfo" "Release" "MinSizeRel")

find_package(helib 1.0.0 EXACT REQUIRED)
find_package(helib 1.1.0 EXACT REQUIRED)
find_package(benchmark REQUIRED)

# Add each benchmark source file to the executable list
add_executable(helib_benchmark bench_thinboot.cpp bench_fatboot.cpp)
target_link_libraries(helib_benchmark benchmark::benchmark_main helib)
# Targets are simply associated with their source files.
set(TRGTS bgv_basic
bgv_thinboot
bgv_fatboot
ckks_basic)

# Sources derived from their targets.
set(SRCS "")
foreach(TRGT ${TRGTS})
list(APPEND SRCS "${TRGT}.cpp")
endforeach()

if(SINGLE_EXEC)
# Add each benchmark source file to the executable list
add_executable(helib_benchmark ${SRCS})
# Specify the libraries each target is dependent upon
target_link_libraries(helib_benchmark benchmark::benchmark_main helib)
else(SINGLE_EXEC)
foreach(TRGT ${TRGTS})
# Add each benchmark source file to the executable list
add_executable(${TRGT} ${TRGT}.cpp)
# Specify the libraries each target is dependent upon
target_link_libraries(${TRGT} benchmark::benchmark_main helib)
endforeach()
endif(SINGLE_EXEC)
44 changes: 32 additions & 12 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Building and running HElib's benchmarks
# Some HElib benchmarks

## Instructions
## Prerequisites

### Build and install HElib

Build and install HElib as in [INSTALL.md](../INSTALL.md).
Build and install HElib as described in [INSTALL.md](../INSTALL.md).

### Build and install google benchmark

Download the library https://github.com/google/benchmark from github, build and
then install it.

```
git clone https://github.com/google/benchmark
cd benchmark
Expand All @@ -20,11 +21,14 @@ make
make install
```

### Write a benchmark test and link to both installed libraries.
## Build benchmark

Benchmarks are found in `HElib/benchmarks` and are grouped by themes; the file
names reflect the themes they belong to. By default, the benchmarks are built as
separate executables. If you prefer to build a single executable then set the
`-DSINGLE_EXEC=ON`. Compiled tests appear in the `bin` directory. Now build
the project.

Write the benchmark in an existing source file or a new one in
`HElib/benchmarks`, adding the new source file to `CMakeLists.txt` if
appropriate, then build the project.
```
cd HElib/benchmarks
mkdir build
Expand All @@ -33,9 +37,25 @@ cmake -Dhelib_DIR=<helib installation dir>/share/cmake/helib -Dbenchmark_DIR=<be
make
```

When writing benchmarks use `BENCHMARK_CAPTURE(custom params)` for custom
params and the extra option `BENCHMARK_CAPTURE()->Iterations(iterations)` for a
specific number of iterations or `BENCHMARK_CAPTURE()->MinTime(time in
seconds)` to set a minimum time for the benchmark to run for.
When writing benchmarks please use `BENCHMARK_CAPTURE(<custom params>)` for
custom parameters and do not forget to add the new target to `CMakeLists.txt`.
Use the extra option `BENCHMARK_CAPTURE()->Iterations(<iterations>)` for a
specific number of iterations or `BENCHMARK_CAPTURE()->MinTime(<time in
seconds>)` to set a minimum time for the benchmark to run for.

NOTE: Both `Iterations` and `MinTime` cannot be used together.

NOTE: Both options cannot be used at the same time.
## Run benchmark

To execute individual tests run the following

```
./bin/<benchmark to run>
```

If you have compiled the tests as a single executable using the
`-DSINGLE_EXEC=ON` flag, you can execute the tests by running the following

```
./bin/helib_benchmark
```
133 changes: 133 additions & 0 deletions benchmarks/bgv_basic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* Copyright (C) 2020 IBM Corp.
* This program is Licensed under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/

#include <benchmark/benchmark.h>
#include <iostream>

#include <helib/helib.h>

#include "bgv_common.h"

namespace {

static void adding_two_ciphertexts(benchmark::State& state, Meta& meta)
{
helib::Ptxt<helib::BGV> ptxt1(meta.data->context);
helib::Ptxt<helib::BGV> ptxt2(meta.data->context);

ptxt1.random();
ptxt2.random();

helib::Ctxt ctxt1(meta.data->publicKey);
helib::Ctxt ctxt2(meta.data->publicKey);

meta.data->publicKey.Encrypt(ctxt1, ptxt1);
meta.data->publicKey.Encrypt(ctxt2, ptxt1);
// Benchmark adding ciphertexts
for (auto _ : state)
ctxt1 += ctxt2;
std::cout << "Additions performed = " << state.iterations() << std::endl;
}

static void multiplying_two_ciphertexts(benchmark::State& state, Meta& meta)
{
helib::Ptxt<helib::BGV> ptxt1(meta.data->context);
helib::Ptxt<helib::BGV> ptxt2(meta.data->context);

ptxt1.random();
ptxt2.random();

helib::Ctxt ctxt1(meta.data->publicKey);
helib::Ctxt ctxt2(meta.data->publicKey);

meta.data->publicKey.Encrypt(ctxt1, ptxt1);
meta.data->publicKey.Encrypt(ctxt2, ptxt2);
// Benchmark adding ciphertexts
for (auto _ : state)
ctxt1.multiplyBy(ctxt2);
std::cout << "Multiplications performed = " << state.iterations()
<< std::endl;
}

static void encrypting_ciphertexts(benchmark::State& state, Meta& meta)
{
helib::Ptxt<helib::BGV> ptxt(meta.data->context);
ptxt.random();

helib::Ctxt ctxt(meta.data->publicKey);

// Benchmark encrypting ciphertexts
for (auto _ : state)
meta.data->publicKey.Encrypt(ctxt, ptxt);
std::cout << "Encryptions performed = " << state.iterations() << std::endl;
}

static void decrypting_ciphertexts(benchmark::State& state, Meta& meta)
{
helib::Ptxt<helib::BGV> ptxt(meta.data->context);
ptxt.random();

helib::Ctxt ctxt(meta.data->publicKey);

meta.data->publicKey.Encrypt(ctxt, ptxt);
helib::Ptxt<helib::BGV> decrypted_result(meta.data->context);

// Benchmark decrypting ciphertexts
for (auto _ : state)
meta.data->secretKey.Decrypt(decrypted_result, ctxt);
std::cout << "Decryptions performed = " << state.iterations() << std::endl;
}

Meta fn;
Params tiny_params(/*m=*/257, /*p=*/2, /*r=*/1, /*L=*/5800);
BENCHMARK_CAPTURE(adding_two_ciphertexts, tiny_params, fn(tiny_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);
BENCHMARK_CAPTURE(multiplying_two_ciphertexts, tiny_params, fn(tiny_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);
BENCHMARK_CAPTURE(encrypting_ciphertexts, tiny_params, fn(tiny_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);
BENCHMARK_CAPTURE(decrypting_ciphertexts, tiny_params, fn(tiny_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);

Params small_params(/*m=*/8009, /*p=*/2, /*r=*/1, /*L=*/5800);
BENCHMARK_CAPTURE(adding_two_ciphertexts, small_params, fn(small_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);
BENCHMARK_CAPTURE(multiplying_two_ciphertexts, small_params, fn(small_params))
->Unit(benchmark::kMillisecond)
->MinTime(200);
BENCHMARK_CAPTURE(encrypting_ciphertexts, small_params, fn(small_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);
BENCHMARK_CAPTURE(decrypting_ciphertexts, small_params, fn(small_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);

Params big_params(/*m=*/32003, /*p=*/2, /*r=*/1, /*L=*/5800);
BENCHMARK_CAPTURE(adding_two_ciphertexts, big_params, fn(big_params))
->Unit(benchmark::kMillisecond)
->Iterations(200);
BENCHMARK_CAPTURE(multiplying_two_ciphertexts, big_params, fn(big_params))
->Unit(benchmark::kMillisecond)
->MinTime(200);
BENCHMARK_CAPTURE(encrypting_ciphertexts, big_params, fn(big_params))
->Unit(benchmark::kMillisecond)
->MinTime(200);
BENCHMARK_CAPTURE(decrypting_ciphertexts, big_params, fn(big_params))
->Unit(benchmark::kMillisecond)
->MinTime(200);

} // namespace
73 changes: 73 additions & 0 deletions benchmarks/bgv_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* Copyright (C) 2020 IBM Corp.
* This program is Licensed under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. See accompanying LICENSE file.
*/

#include <memory>

#include <helib/helib.h>

struct Params
{
const long m, p, r, L;
const std::vector<long> gens;
const std::vector<long> ords;
Params(long _m,
long _p,
long _r,
long _L,
const std::vector<long>& _gens = {},
const std::vector<long>& _ords = {}) :
m(_m), p(_p), r(_r), L(_L), gens(_gens), ords(_ords)
{}
Params(const Params& other) :
Params(other.m, other.p, other.r, other.L, other.gens, other.ords)
{}
bool operator!=(Params& other) const { return !(*this == other); }
bool operator==(Params& other) const
{
return m == other.m && p == other.p && r == other.r && L == other.L &&
gens == other.gens && ords == other.ords;
}
};

struct ContextAndKeys
{
const Params params;

helib::Context context;
helib::SecKey secretKey;
const helib::PubKey publicKey;
const helib::EncryptedArray& ea;

ContextAndKeys(Params& _params) :
params(_params),
context(params.m, params.p, params.r, params.gens, params.ords),
secretKey((helib::buildModChain(context, params.L, /*c=*/2), context)),
publicKey((secretKey.GenSecKey(),
helib::addSome1DMatrices(secretKey),
secretKey)),
ea(*(context.ea))
{
context.printout();
}
};

struct Meta
{
std::unique_ptr<ContextAndKeys> data;
Meta& operator()(Params& params)
{
// Only change if nullptr or different.
if (data == nullptr || data->params != params)
data = std::make_unique<ContextAndKeys>(params);
return *this;
}
};
Loading

0 comments on commit f8230cd

Please sign in to comment.