/* * @author TPOC: contact@palisade-crypto.org * * @copyright Copyright (c) 2019, New Jersey Institute of Technology (NJIT) * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. THIS SOFTWARE IS * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #define _USE_MATH_DEFINES #include "benchmark/benchmark.h" #include "palisade.h" #include #include #include "vechelper.h" using namespace std; using namespace lbcrypto; namespace lbcrypto { static vector tow_args({1, 2, 4, 8}); static const usint DCRTBITS = 60; static const usint RING_DIM_LOG = 12; static const size_t POLY_NUM = 16; static const size_t POLY_NUM_M1 = (POLY_NUM - 1); static NativePoly makeElement(shared_ptr params, Format format) { NativeVector vec = makeVector(params->GetRingDimension(), params->GetModulus()); NativePoly elem(params); elem.SetValues(vec, format); return elem; } static M2DCRTPoly makeElement(shared_ptr p, Format format) { shared_ptr params( new M2Params(p->GetCyclotomicOrder(), p->GetModulus(), 1)); M2Vector vec = makeVector(params->GetRingDimension(), params->GetModulus()); M2DCRTPoly::PolyLargeType bigE(params); bigE.SetValues(vec, format); M2DCRTPoly elem(bigE, p); return elem; } static void GenerateNativeParms(shared_ptr &parmArray) { uint32_t m = (1 << (RING_DIM_LOG + 1)); NativeInteger firstInteger = FirstPrime(DCRTBITS, m); NativeInteger modulo = PreviousPrime(firstInteger, m); NativeInteger root = RootOfUnity(m, modulo); ChineseRemainderTransformFTT::PreCompute(root, m, modulo); parmArray = shared_ptr(new ILNativeParams(m, modulo, root)); } static void GenerateDCRTParms(map> &parmArray) { for (usint t : tow_args) { uint32_t m = (1 << (RING_DIM_LOG + 1)); vector moduli(t); vector roots(t); NativeInteger firstInteger = FirstPrime(DCRTBITS, m); moduli[0] = PreviousPrime(firstInteger, m); roots[0] = RootOfUnity(m, moduli[0]); for (size_t i = 1; i < t; i++) { moduli[i] = PreviousPrime(moduli[i - 1], m); roots[i] = RootOfUnity(m, moduli[i]); } ChineseRemainderTransformFTT::PreCompute(roots, m, moduli); parmArray[t] = shared_ptr(new M2DCRTParams(m, moduli, roots)); } } static void GeneratePolys(shared_ptr parmArray, shared_ptr> &polyArrayEval, shared_ptr> &polyArrayCoef) { vector vecEval; for (size_t i = 0; i < POLY_NUM; i++) { vecEval.push_back(makeElement(parmArray, Format::EVALUATION)); } polyArrayEval = make_shared>(std::move(vecEval)); vector vecCoef; for (size_t i = 0; i < POLY_NUM; i++) { vecCoef.push_back(makeElement(parmArray, Format::COEFFICIENT)); } polyArrayCoef = make_shared>(std::move(vecCoef)); } static void GenerateDCRTPolys( map> &parmArray, map>> &polyArrayEval, map>> &polyArrayCoef) { for (auto &pair : parmArray) { vector vecEval; for (size_t i = 0; i < POLY_NUM; i++) { vecEval.push_back(makeElement(parmArray[pair.first], Format::EVALUATION)); } polyArrayEval[pair.first] = make_shared>(std::move(vecEval)); vector vecCoef; for (size_t i = 0; i < POLY_NUM; i++) { vecCoef.push_back( makeElement(parmArray[pair.first], Format::COEFFICIENT)); } polyArrayCoef[pair.first] = make_shared>(std::move(vecCoef)); } } } // namespace lbcrypto shared_ptr Nativeparms; map> DCRTparms; shared_ptr> NativepolysEval; map>> DCRTpolysEval; shared_ptr> NativepolysCoef; map>> DCRTpolysCoef; class Setup { public: Setup() { GenerateNativeParms(Nativeparms); GenerateDCRTParms(DCRTparms); cerr << "Generating polynomials for the benchmark..." << endl; GeneratePolys(Nativeparms, NativepolysEval, NativepolysCoef); GenerateDCRTPolys(DCRTparms, DCRTpolysEval, DCRTpolysCoef); cerr << "Polynomials for the benchmark are generated" << endl; } } TestParameters; static void DCRTArguments(benchmark::internal::Benchmark *b) { for (usint t : tow_args) { b->ArgName("towers")->Arg(t); } } static void Native_add(benchmark::State &state) { // benchmark shared_ptr> polys = NativepolysEval; NativePoly *a, *b, c; size_t i = 0; while (state.KeepRunning()) { a = &(polys->operator[](i)); b = &(polys->operator[](i + 1)); i += 2; i = i & POLY_NUM_M1; c = a->Plus(*b); } } BENCHMARK(Native_add)->Unit(benchmark::kMicrosecond); static void DCRT_add(benchmark::State &state) { // benchmark shared_ptr> polys = DCRTpolysEval[state.range(0)]; M2DCRTPoly *a, *b, c; size_t i = 0; while (state.KeepRunning()) { a = &(polys->operator[](i)); b = &(polys->operator[](i + 1)); i += 2; i = i & POLY_NUM_M1; c = a->Plus(*b); } } BENCHMARK(DCRT_add)->Unit(benchmark::kMicrosecond)->Apply(DCRTArguments); static void Native_mul(benchmark::State &state) { shared_ptr> polys = NativepolysEval; NativePoly *a, *b, c; size_t i = 0; while (state.KeepRunning()) { a = &(polys->operator[](i)); b = &(polys->operator[](i + 1)); i += 2; i = i & POLY_NUM_M1; c = a->Times(*b); } } BENCHMARK(Native_mul)->Unit(benchmark::kMicrosecond); static void DCRT_mul(benchmark::State &state) { shared_ptr> polys = DCRTpolysEval[state.range(0)]; M2DCRTPoly *a, *b, c; size_t i = 0; while (state.KeepRunning()) { a = &(polys->operator[](i)); b = &(polys->operator[](i + 1)); i += 2; i = i & POLY_NUM_M1; c = a->Times(*b); } } BENCHMARK(DCRT_mul)->Unit(benchmark::kMicrosecond)->Apply(DCRTArguments); static void Native_ntt(benchmark::State &state) { shared_ptr> polys = NativepolysCoef; NativePoly a; size_t i = 0; while (state.KeepRunning()) { a = polys->operator[](i); i++; i = i & POLY_NUM_M1; a.SwitchFormat(); } } BENCHMARK(Native_ntt)->Unit(benchmark::kMicrosecond); static void DCRT_ntt(benchmark::State &state) { shared_ptr> polys = DCRTpolysCoef[state.range(0)]; M2DCRTPoly a; size_t i = 0; while (state.KeepRunning()) { a = polys->operator[](i); i++; i = i & POLY_NUM_M1; a.SwitchFormat(); } } BENCHMARK(DCRT_ntt)->Unit(benchmark::kMicrosecond)->Apply(DCRTArguments); static void Native_intt(benchmark::State &state) { shared_ptr> polys = NativepolysEval; NativePoly a; size_t i = 0; while (state.KeepRunning()) { a = polys->operator[](i); i++; i = i & POLY_NUM_M1; a.SwitchFormat(); } } BENCHMARK(Native_intt)->Unit(benchmark::kMicrosecond); static void DCRT_intt(benchmark::State &state) { shared_ptr> polys = DCRTpolysEval[state.range(0)]; M2DCRTPoly a; size_t i = 0; while (state.KeepRunning()) { a = polys->operator[](i); i++; i = i & POLY_NUM_M1; a.SwitchFormat(); } } BENCHMARK(DCRT_intt)->Unit(benchmark::kMicrosecond)->Apply(DCRTArguments); BENCHMARK_MAIN();