Skip to content

Commit

Permalink
feat(bench): add pairing and G2 bench for zkalc and nimble build script
Browse files Browse the repository at this point in the history
  • Loading branch information
mratsim committed Jul 12, 2024
1 parent 0c7d22e commit 3ba3f98
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 64 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,20 @@ jobs:
cd constantine
CTT_ASM=0 cargo test -- --nocapture
- name: Compile Constantine Zkalc benchmark (no assembly)
if: matrix.target.BACKEND == 'NO_ASM'
shell: bash
run: |
cd constantine
CTT_ASM=0 nimble make_zkalc
- name: Compile Constantine Zkalc benchmark (with assembly)
if: matrix.target.BACKEND == 'ASM'
shell: bash
run: |
cd constantine
nimble make_zkalc
- name: Run Constantine in-depth tests (Unix - with GMP, with Assembly)
if: runner.os != 'Windows' && matrix.target.BACKEND == 'ASM'
shell: bash
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Executables shall be put in an ignored build/ directory
# Build artifacts shall be put in an ignored build/ directory
# Ignore dynamic, static libs and libtool archive files
# -----------------------------------------------------------------------------------------
build/
Expand Down Expand Up @@ -54,4 +54,4 @@ Cargo.lock
# Perf artifacts
# -----------------------------------------------------------------------------------------
perf.data
perf.data.old
perf.data.old
118 changes: 60 additions & 58 deletions benchmarks/zkalc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
# https://github.com/mmaker/zkalc

import
constantine/threadpool,
constantine/hashes,
constantine/lowlevel_fields,
# constantine/lowlevel_extension_fields,
constantine/math/extension_fields,
constantine/lowlevel_elliptic_curves,
constantine/lowlevel_elliptic_curves_parallel,
# constantine/lowlevel_extension_fields,
constantine/lowlevel_pairing_curves,
constantine/threadpool,

# Helpers
helpers/prng_unsafe,
# Standard library
Expand Down Expand Up @@ -278,13 +280,13 @@ proc benchEcMul(rng: var RngState, EC: typedesc, useVartime: bool): ZkalcBenchDe

type BenchMsmContext[EC] = object
numInputs: int
coefs: seq[getBigInt(EC.F.Name, kScalarField)]
coefs: seq[getBigInt(EC.getName(), kScalarField)]
points: seq[affine(EC)]

proc createBenchMsmContext*(rng: var RngState, EC: typedesc, maxNumInputs: int): BenchMsmContext[EC] =
let tp = Threadpool.new()

type Big = EC.F.Name.getBigInt(kScalarField)
type Big = typeof(result.coefs[0])
type ECaff = affine(EC)

result.numInputs = maxNumInputs
Expand Down Expand Up @@ -327,7 +329,7 @@ proc benchEcMsm[EC](ctx: BenchMsmContext[EC]): ZkalcBenchDetails =
const G =
when EC.G == G1: "𝔾1"
else: "𝔾2"
const curve = EC.F.Name
const curve = EC.getName()

let tp = Threadpool.new()
var size = 2
Expand Down Expand Up @@ -405,46 +407,46 @@ func random_point*(rng: var RngState, EC: typedesc): EC {.noInit.} =
result = rng.random_unsafe(EC)
result.clearCofactor()

# proc benchPairing*(rng: var RngState, curve: static Algebra): ZkalcBenchDetails =
# let
# P = rng.random_point(EC_ShortW_Aff[Fp[curve], G1])
# Q = rng.random_point(EC_ShortW_Aff[Fp2[curve], G2])
proc benchPairing*(rng: var RngState, curve: static Algebra): ZkalcBenchDetails =
let
P = rng.random_point(EC_ShortW_Aff[Fp[curve], G1])
Q = rng.random_point(EC_ShortW_Aff[Fp2[curve], G2])

# var f: Fp12[curve]
# let stats = bench():
# f.pairing(P, Q)
var f: Fp12[curve]
let stats = bench():
f.pairing(P, Q)

# report("Pairing", curve, stats)
# stats.toZkalc()
report("Pairing", curve, stats)
stats.toZkalc()

# proc benchMultiPairing*(rng: var RngState, curve: static Algebra, maxNumInputs: int): ZkalcBenchDetails =
# var
# Ps = newSeq[EC_ShortW_Aff[Fp[curve], G1]](maxNumInputs)
# Qs = newSeq[EC_ShortW_Aff[Fp2[curve], G2]](maxNumInputs)
proc benchMultiPairing*(rng: var RngState, curve: static Algebra, maxNumInputs: int): ZkalcBenchDetails =
var
Ps = newSeq[EC_ShortW_Aff[Fp[curve], G1]](maxNumInputs)
Qs = newSeq[EC_ShortW_Aff[Fp2[curve], G2]](maxNumInputs)

# stdout.write &"Generating {maxNumInputs} (𝔾1, 𝔾2) pairs ... "
# stdout.flushFile()
stdout.write &"Generating {maxNumInputs} (𝔾1, 𝔾2) pairs ... "
stdout.flushFile()

# let start = getMonotime()
let start = getMonotime()

# for i in 0 ..< maxNumInputs:
# Ps[i] = rng.random_point(typeof(Ps[0]))
# Qs[i] = rng.random_point(typeof(Qs[0]))
for i in 0 ..< maxNumInputs:
Ps[i] = rng.random_point(typeof(Ps[0]))
Qs[i] = rng.random_point(typeof(Qs[0]))

# let stop = getMonotime()
# stdout.write &"in {float64(inNanoSeconds(stop-start)) / 1e6:6.3f} ms\n"
# separator()
let stop = getMonotime()
stdout.write &"in {float64(inNanoSeconds(stop-start)) / 1e6:6.3f} ms\n"
separator()

# var size = 2
# while size <= maxNumInputs:
# var f{.noInit.}: Fp12[curve]
# let stats = bench():
# f.pairing(Ps.toOpenArray(0, size-1), Qs.toOpenArray(0, size-1))
var size = 2
while size <= maxNumInputs:
var f{.noInit.}: Fp12[curve]
let stats = bench():
f.pairing(Ps.toOpenArray(0, size-1), Qs.toOpenArray(0, size-1))

# report("Multipairing " & align($size, 5), curve, stats)
# result.append(stats, size)
report("Multipairing " & align($size, 5), curve, stats)
result.append(stats, size)

# size *= 2
size *= 2

# Run benches
# -------------------------------------------------------------------------------------
Expand Down Expand Up @@ -480,35 +482,35 @@ proc runBenches(curve: static Algebra, useVartime: bool) =
zkalc.hash_G1 = rng.benchEcHashToCurve(EcG1)
separator()

# # Pairing-friendly curve only
# # --------------------------------------------------------------------
# Pairing-friendly curve only
# --------------------------------------------------------------------

# when curve.isPairingFriendly():
when curve.isPairingFriendly():

# # Elliptic curve 𝔾2
# # --------------------------------------------------------------------
# Elliptic curve 𝔾2
# --------------------------------------------------------------------

# type EcG2 = EC_ShortW_Jac[Fp2[curve], G2] # For now we only supports G2 on Fp2 (not Fp like BW6 or Fp4 like BLS24)
type EcG2 = EC_ShortW_Jac[Fp2[curve], G2] # For now we only supports G2 on Fp2 (not Fp like BW6 or Fp4 like BLS24)

# zkalc.add_g2 = rng.benchEcAdd(EcG2, useVartime)
# zkalc.mul_g2 = rng.benchEcMul(EcG2, useVartime)
# separator()
# let ctxG2 = rng.createBenchMsmContext(EcG2, maxNumInputs = 2097152)
# separator()
# zkalc.msm_g2 = benchEcMsm(ctxG2)
# separator()
# zkalc.is_in_sub_G2 = rng.benchEcIsInSubgroup(EcG2)
# when curve in {BN254_Snarks, BLS12_381}:
# zkalc.hash_G2 = rng.benchEcHashToCurve(EcG2)
# separator()
zkalc.add_g2 = rng.benchEcAdd(EcG2, useVartime)
zkalc.mul_g2 = rng.benchEcMul(EcG2, useVartime)
separator()
let ctxG2 = rng.createBenchMsmContext(EcG2, maxNumInputs = 2097152)
separator()
zkalc.msm_g2 = benchEcMsm(ctxG2)
separator()
zkalc.is_in_sub_G2 = rng.benchEcIsInSubgroup(EcG2)
when curve in {BN254_Snarks, BLS12_381}:
zkalc.hash_G2 = rng.benchEcHashToCurve(EcG2)
separator()

# # Pairings
# # --------------------------------------------------------------------
# Pairings
# --------------------------------------------------------------------

# zkalc.pairing = rng.benchPairing(curve)
# separator()
# zkalc.multipairing = rng.benchMultiPairing(curve, maxNumInputs = 1024)
# separator()
zkalc.pairing = rng.benchPairing(curve)
separator()
zkalc.multipairing = rng.benchMultiPairing(curve, maxNumInputs = 1024)
separator()

proc main() =
let cmd = commandLineParams()
Expand Down
12 changes: 12 additions & 0 deletions bin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Ignore all
*

# Unignore all with extensions
!*.*

# Unignore all dirs
!*/

# Reignore executables
*.exe
*.out
9 changes: 9 additions & 0 deletions constantine.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@ task make_lib_rust, "Build Constantine library (use within a Rust build.rs scrip
else: "--passC:-fPIC"
genStaticLib(rustOutDir, rustOutDir/"nimcache", extflags)

task make_zkalc, "Build a benchmark executable for zkalc (with Clang)":
exec "nim c --cc:clang " &
releaseBuildOptions(bmBinary) &
" --threads:on " &
" --out:bin/constantine-bench-zkalc " &
" --nimcache:nimcache/bench_zkalc " &
" benchmarks/zkalc.nim"

proc testLib(path, testName: string, useGMP: bool) =
let dynlibName = if defined(windows): "constantine.dll"
elif defined(macosx) or defined(macos): "libconstantine.dylib"
Expand Down Expand Up @@ -639,6 +647,7 @@ const benchDesc = [
"bench_eth_eip2537_subgroup_checks_impact",
"bench_verkle_primitives",
"bench_eth_evm_precompiles",
# "zkalc", # Already tested through make_zkalc
]

# For temporary (hopefully) investigation that can only be reproduced in CI
Expand Down
1 change: 0 additions & 1 deletion constantine/lowlevel_extension_fields.nim
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export
# ------------------------------------------------------------

export
extension_fields.Name,
extension_fields.Fp2,
# TODO: deal with Fp2->Fp6 vs Fp3->Fp6 and Fp2->Fp6->Fp12 vs Fp2->Fp4->Fp12
# extension_fields.Fp4,
Expand Down
4 changes: 2 additions & 2 deletions constantine/math/pairings/pairings_generic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ func pairing*[Name: static Algebra](gt: var Fp12[Name], P, Q: auto) {.inline.} =
else:
{.error: "Pairing not implemented for " & $Name.}

func millerLoop*[Name](gt: var Fp12[Name], Q, P: auto, n: int) {.inline.} =
func millerLoop*[Name: static Algebra](gt: var Fp12[Name], Q, P: auto, n: int) {.inline.} =
when Name == BN254_Snarks:
gt.millerLoopGenericBN(Q, P, n)
else:
gt.millerLoopAddchain(Q, P, n)

func finalExp*[Name](gt: var Fp12[Name]){.inline.} =
func finalExp*[Name: static Algebra](gt: var Fp12[Name]){.inline.} =
gt.finalExpEasy()
when family(Name) == BarretoNaehrig:
gt.finalExpHard_BN()
Expand Down
2 changes: 1 addition & 1 deletion constantine/named/zoo_subgroups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export
func clearCofactor*[EC](P: var EC) {.inline.} =
## Clear the cofactor of a point on the curve
## From a point on the curve, returns a point on the subgroup of order r
when EC.F.Name in {BN254_Nogami, BN254_Snarks, BLS12_377, BLS12_381}:
when EC.getName() in {BN254_Nogami, BN254_Snarks, BLS12_377, BLS12_381}:
P.clearCofactorFast()
else:
P.clearCofactorReference()

0 comments on commit 3ba3f98

Please sign in to comment.