#define PUT(x) std::cout << #x "=" << (x) << std::endl #include #include #include #include #include typedef mcl::FpT Fp; typedef mcl::Fp2T Fp2; typedef mcl::FpDblT FpDbl; typedef mcl::Fp6T Fp6; typedef mcl::Fp12T Fp12; typedef mcl::fp::Unit Unit; void mul9(const mcl::fp::Op& op, Unit *y, const Unit *x, const Unit *p) { const size_t maxN = sizeof(Fp) / sizeof(Unit); Unit tmp[maxN]; op.fp_add(tmp, x, x, p); // 2x op.fp_add(tmp, tmp, tmp, p); // 4x op.fp_add(tmp, tmp, tmp, p); // 8x op.fp_add(y, tmp, x, p); // 9x } void benchRaw(const char *p, mcl::fp::Mode mode) { Fp::init(p, mode); Fp2::init(1); const size_t maxN = sizeof(Fp) / sizeof(Unit); const mcl::fp::Op& op = Fp::getOp(); cybozu::XorShift rg; Fp fx, fy; fx.setRand(rg); fy.setRand(rg); Unit ux[maxN * 2] = {}; Unit uy[maxN * 2] = {}; Unit uz[maxN * 2] = {}; memcpy(ux, fx.getUnit(), sizeof(Unit) * op.N); memcpy(ux + op.N, fx.getUnit(), sizeof(Unit) * op.N); memcpy(uy, fy.getUnit(), sizeof(Unit) * op.N); memcpy(ux + op.N, fx.getUnit(), sizeof(Unit) * op.N); double fp_addT, fp_subT; double fp_addPreT, fp_subPreT; double fp_sqrT, fp_mulT; double fp_mulUnitT; double mul9T; double fp_mulUnitPreT; double fpN1_modT; double fpDbl_addT, fpDbl_subT; double fpDbl_sqrPreT, fpDbl_mulPreT, fpDbl_modT; double fp2_sqrT, fp2_mulT; CYBOZU_BENCH_T(fp_addT, op.fp_add, uz, ux, uy, op.p); CYBOZU_BENCH_T(fp_subT, op.fp_sub, uz, uy, ux, op.p); CYBOZU_BENCH_T(fp_addPreT, op.fp_addPre, uz, ux, uy); CYBOZU_BENCH_T(fp_subPreT, op.fp_subPre, uz, uy, ux); CYBOZU_BENCH_T(fp_sqrT, op.fp_sqr, uz, ux, op.p); CYBOZU_BENCH_T(fp_mulT, op.fp_mul, uz, ux, uy, op.p); CYBOZU_BENCH_T(fp_mulUnitT, op.fp_mulUnit, uz, ux, 9, op.p); CYBOZU_BENCH_T(mul9T, mul9, op, uz, ux, op.p); CYBOZU_BENCH_T(fp_mulUnitPreT, op.fp_mulUnitPre, ux, ux, 9); CYBOZU_BENCH_T(fpN1_modT, op.fpN1_mod, ux, uy, op.p); CYBOZU_BENCH_T(fpDbl_addT, op.fpDbl_add, uz, ux, uy, op.p); CYBOZU_BENCH_T(fpDbl_subT, op.fpDbl_sub, uz, uy, ux, op.p); CYBOZU_BENCH_T(fpDbl_sqrPreT, op.fpDbl_sqrPre, uz, ux); CYBOZU_BENCH_T(fpDbl_mulPreT, op.fpDbl_mulPre, uz, ux, uy); CYBOZU_BENCH_T(fpDbl_modT, op.fpDbl_mod, uz, ux, op.p); Fp2 f2x, f2y; f2x.a = fx; f2x.b = fy; f2y = f2x; CYBOZU_BENCH_T(fp2_sqrT, Fp2::sqr, f2x, f2x); CYBOZU_BENCH_T(fp2_mulT, Fp2::mul, f2x, f2x, f2y); printf("%s\n", mcl::fp::ModeToStr(mode)); const char *tStrTbl[] = { "fp_add", "fp_sub", "addPre", "subPre", "fp_sqr", "fp_mul", "mulUnit", "mul9", "mulUnitP", "fpN1_mod", "D_add", "D_sub", "D_sqrPre", "D_mulPre", "D_mod", "fp2_sqr", "fp2_mul", }; for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tStrTbl); i++) { printf(" %8s", tStrTbl[i]); } printf("\n"); const double tTbl[] = { fp_addT, fp_subT, fp_addPreT, fp_subPreT, fp_sqrT, fp_mulT, fp_mulUnitT, mul9T, fp_mulUnitPreT, fpN1_modT, fpDbl_addT, fpDbl_subT, fpDbl_sqrPreT, fpDbl_mulPreT, fpDbl_modT, fp2_sqrT, fp2_mulT, }; for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tTbl); i++) { printf(" %8.2f", tTbl[i]); } printf("\n"); } int main(int argc, char *argv[]) try { cybozu::Option opt; size_t bitSize; opt.appendOpt(&bitSize, 0, "s", ": bitSize"); opt.appendHelp("h", ": show this message"); if (!opt.parse(argc, argv)) { opt.usage(); return 1; } const char *tbl[] = { // N = 2 "0x0000000000000001000000000000000d", "0x7fffffffffffffffffffffffffffffff", "0x8000000000000000000000000000001d", "0xffffffffffffffffffffffffffffff61", // N = 3 "0x000000000000000100000000000000000000000000000033", // min prime "0x70000000000000000000000000000000000000000000001f", "0x800000000000000000000000000000000000000000000005", "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", "0xfffffffffffffffffffffffffffffffeffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime // N = 4 "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime "0x2523648240000001ba344d80000000086121000000000013a700000000000013", // BN254 "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", // Snark "0x7523648240000001ba344d80000000086121000000000013a700000000000017", "0x800000000000000000000000000000000000000000000000000000000000005f", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime "0x80000000000000000000000000000000000000000000000000000000000000000000000000000009", // 5 "0x800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000171", // 6 "0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063", // 7 "0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f", // 8 }; for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { const char *p = tbl[i]; if (bitSize > 0 && (strlen(p) - 2) * 4 != bitSize) { continue; } printf("prime=%s\n", p); benchRaw(tbl[i], mcl::fp::FP_GMP); benchRaw(tbl[i], mcl::fp::FP_GMP_MONT); #ifdef MCL_USE_LLVM benchRaw(tbl[i], mcl::fp::FP_LLVM); benchRaw(tbl[i], mcl::fp::FP_LLVM_MONT); #endif #ifdef MCL_USE_XBYAK benchRaw(tbl[i], mcl::fp::FP_XBYAK); #endif } } catch (std::exception& e) { printf("ERR %s\n", e.what()); return 1; }