Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-Scalar-Multiplication / Linear combination #220

Merged
merged 35 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5e720cc
unoptimized msm
mratsim Feb 1, 2023
390f7e4
MSM: reorder loops
mratsim Feb 7, 2023
87244b8
add a signed windowed recoding technique
mratsim Feb 8, 2023
eff4d60
improve wNAF table access
mratsim Feb 8, 2023
ad61b54
use batchAffine
mratsim Feb 8, 2023
5d83f88
revamp EC tests
mratsim Feb 8, 2023
229cd83
MSM signed digit support
mratsim Feb 8, 2023
2d72e75
refactor MSM: recode signed ahead of time
mratsim Feb 9, 2023
9fe0797
missing test vector
mratsim Feb 9, 2023
b860d77
refactor allocs and Alloca sideeffect
mratsim Feb 9, 2023
400603e
add an endomorphism threshold
mratsim Feb 9, 2023
9b86495
Add Jacobian extended coordinates
mratsim Feb 9, 2023
10fc577
refactor recodings, prepare for parallelizable on-the-fly signed reco…
mratsim Feb 10, 2023
6afca45
recoding changes, introduce proper NAF for pairings
mratsim Feb 10, 2023
61f276e
more pairings refactoring, introduce miller accumulator for EVM
mratsim Feb 10, 2023
8637890
some optim to the addchain miller loop
mratsim Feb 10, 2023
92a19c9
start optimizing multi-pairing
mratsim Feb 10, 2023
53967cf
finish multi-miller loop refactoring
mratsim Feb 10, 2023
e2ac98d
minor tuning
mratsim Feb 10, 2023
56f5dda
MSM: signed encoding suitable for parallelism (no precompute)
mratsim Feb 11, 2023
0ddb58f
cleanup signed window encoding
mratsim Feb 11, 2023
7e160ae
add prefetching
mratsim Feb 11, 2023
8295a4d
add metering
mratsim Feb 11, 2023
e6ef0de
properly init result to infinity
mratsim Feb 11, 2023
d427dd5
comment on prefetching
mratsim Feb 12, 2023
52b9fc6
introduce vartime inversion for batch additions
mratsim Feb 12, 2023
119fc05
fix JacExt infinity conversion
mratsim Feb 12, 2023
c7fbae0
add batchAffine for MSM, though slower than JacExtended at the moment
mratsim Feb 12, 2023
3d0bf5c
add a batch affine scheduler for MSM
mratsim Feb 15, 2023
c6c67c6
Add Multi-Scalar-Multiplication endomorphism acceleration
mratsim Feb 15, 2023
9a3726f
some tuning
mratsim Feb 15, 2023
1d70f64
signed integer fixes + 32-bit + tuning
mratsim Feb 16, 2023
23722f4
Some more tuning
mratsim Feb 16, 2023
d415bfc
common msm bench + don't use affine for c < 9
mratsim Feb 16, 2023
a5edb54
nit
mratsim Feb 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions benchmarks/bench_ec_g1.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import
../constantine/math/arithmetic,
../constantine/math/elliptic/[
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian],
ec_shortweierstrass_jacobian,
ec_shortweierstrass_jacobian_extended],
# Helpers
./bench_elliptic_template

Expand Down Expand Up @@ -46,33 +47,32 @@ proc main() =
const curve = AvailableCurves[i]
addBench(ECP_ShortW_Prj[Fp[curve], G1], Iters)
addBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
addBench(ECP_ShortW_JacExt[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_Prj[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_JacExt[Fp[curve], G1], Iters)
doublingBench(ECP_ShortW_Prj[Fp[curve], G1], Iters)
doublingBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
doublingBench(ECP_ShortW_JacExt[Fp[curve], G1], Iters)
separator()
affFromProjBench(ECP_ShortW_Prj[Fp[curve], G1], MulIters)
affFromJacBench(ECP_ShortW_Jac[Fp[curve], G1], MulIters)
separator()
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Prj[Fp[curve], G1], MulIters)
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Jac[Fp[curve], G1], MulIters)
for numPoints in [10, 100, 1000, 10000]:
let batchIters = max(1, Iters div numPoints)
affFromProjBatchBench(ECP_ShortW_Prj[Fp[curve], G1], numPoints, useBatching = false, batchIters)
separator()
scalarMulUnsafeMinHammingWeightRecodingBench(ECP_ShortW_Prj[Fp[curve], G1], MulIters)
scalarMulUnsafeMinHammingWeightRecodingBench(ECP_ShortW_Jac[Fp[curve], G1], MulIters)
for numPoints in [10, 100, 1000, 10000]:
let batchIters = max(1, Iters div numPoints)
affFromProjBatchBench(ECP_ShortW_Prj[Fp[curve], G1], numPoints, useBatching = true, batchIters)
separator()
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], window = 5, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], window = 5, MulIters)
for numPoints in [10, 100, 1000, 10000]:
let batchIters = max(1, Iters div numPoints)
affFromJacBatchBench(ECP_ShortW_Jac[Fp[curve], G1], numPoints, useBatching = false, batchIters)
separator()
scalarMulEndo(ECP_ShortW_Prj[Fp[curve], G1], MulIters)
scalarMulEndoWindow(ECP_ShortW_Prj[Fp[curve], G1], MulIters)
scalarMulEndo(ECP_ShortW_Jac[Fp[curve], G1], MulIters)
scalarMulEndoWindow(ECP_ShortW_Jac[Fp[curve], G1], MulIters)
for numPoints in [10, 100, 1000, 10000]:
let batchIters = max(1, Iters div numPoints)
affFromJacBatchBench(ECP_ShortW_Jac[Fp[curve], G1], numPoints, useBatching = true, batchIters)
separator()
separator()

Expand Down
35 changes: 25 additions & 10 deletions benchmarks/bench_ec_g1_batch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import
ec_shortweierstrass_affine,
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian,
ec_shortweierstrass_jacobian_extended,
ec_shortweierstrass_batch_ops_parallel],
../constantine/platforms/threadpool/threadpool,
# Helpers
Expand All @@ -38,7 +39,7 @@ proc multiAddParallelBench*(EC: typedesc, numPoints: int, iters: int) =
var tp = Threadpool.new()

bench("EC parallel batch add (" & align($tp.numThreads, 2) & " threads) " & $EC.G & " (" & $numPoints & " points)", EC, iters):
tp.sum_batch_vartime_parallel(r, points)
tp.sum_reduce_vartime_parallel(r, points)

tp.shutdown()

Expand All @@ -57,41 +58,55 @@ const AvailableCurves = [
BLS12_381,
]

# const testNumPoints = [10, 100, 1000, 10000, 100000]
const testNumPoints = [4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 65536, 131072]

proc main() =
separator()
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
addBench(ECP_ShortW_Prj[Fp[curve], G1], Iters)
addBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_Prj[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
doublingBench(ECP_ShortW_Prj[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_Prj[Fp[curve], G1], Iters)
addBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
doublingBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_Jac[Fp[curve], G1], Iters)
addBench(ECP_ShortW_JacExt[Fp[curve], G1], Iters)
doublingBench(ECP_ShortW_JacExt[Fp[curve], G1], Iters)
mixedAddBench(ECP_ShortW_JacExt[Fp[curve], G1], Iters)
separator()
for numPoints in [10, 100, 1000, 10000, 100000, 1000000]:
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddBench(ECP_ShortW_Prj[Fp[curve], G1], numPoints, useBatching = false, batchIters)
separator()
for numPoints in [10, 100, 1000, 10000, 100000, 1000000]:
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddBench(ECP_ShortW_Prj[Fp[curve], G1], numPoints, useBatching = true, batchIters)
separator()
for numPoints in [10, 100, 1000, 10000, 100000, 1000000]:
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddParallelBench(ECP_ShortW_Prj[Fp[curve], G1], numPoints, batchIters)
separator()
for numPoints in [10, 100, 1000, 10000, 100000, 1000000]:
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddBench(ECP_ShortW_Jac[Fp[curve], G1], numPoints, useBatching = false, batchIters)
separator()
for numPoints in [10, 100, 1000, 10000, 100000, 1000000]:
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddBench(ECP_ShortW_Jac[Fp[curve], G1], numPoints, useBatching = true, batchIters)
separator()
for numPoints in [10, 100, 1000, 10000, 100000, 1000000]:
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddParallelBench(ECP_ShortW_Jac[Fp[curve], G1], numPoints, batchIters)
separator()
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddBench(ECP_ShortW_JacExt[Fp[curve], G1], numPoints, useBatching = false, batchIters)
separator()
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
multiAddBench(ECP_ShortW_JacExt[Fp[curve], G1], numPoints, useBatching = true, batchIters)
separator()
separator()

main()
Expand Down
60 changes: 60 additions & 0 deletions benchmarks/bench_ec_g1_msm_bls12_381.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.

import
# Internals
../constantine/math/config/curves,
../constantine/math/arithmetic,
../constantine/math/elliptic/[
ec_shortweierstrass_affine,
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian,
ec_scalar_mul,
ec_multi_scalar_mul],
../constantine/math/constants/zoo_subgroups,
# Helpers
../helpers/prng_unsafe,
./bench_elliptic_template,
./bench_blueprint

# ############################################################
#
# Benchmark of the G1 group of
# Short Weierstrass elliptic curves
# in (homogeneous) projective coordinates
#
# ############################################################


const Iters = 10_000
const AvailableCurves = [
BLS12_381,
]

# const testNumPoints = [10, 100, 1000, 10000, 100000]
const testNumPoints = [8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192,
16384, 32768, 65536, 131072, 262144]

proc main() =
separator()
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
separator()
# for numPoints in testNumPoints:
# let batchIters = max(1, Iters div numPoints)
# msmBench(ECP_ShortW_Prj[Fp[curve], G1], numPoints, batchIters)
# separator()
# separator()
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
msmBench(ECP_ShortW_Jac[Fp[curve], G1], numPoints, batchIters)
separator()
separator()

main()
notes()
59 changes: 59 additions & 0 deletions benchmarks/bench_ec_g1_msm_bn254_snarks.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.

import
# Internals
../constantine/math/config/curves,
../constantine/math/arithmetic,
../constantine/math/elliptic/[
ec_shortweierstrass_affine,
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian,
ec_scalar_mul,
ec_multi_scalar_mul],
../constantine/math/constants/zoo_subgroups,
# Helpers
../helpers/prng_unsafe,
./bench_elliptic_template,
./bench_blueprint

# ############################################################
#
# Benchmark of the G1 group of
# Short Weierstrass elliptic curves
# in (homogeneous) projective coordinates
#
# ############################################################


const Iters = 10_000
const AvailableCurves = [
BN254_Snarks,
]

const testNumPoints = [10, 100, 1000, 10000, 100000]
# const testNumPoints = [64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072]

proc main() =
separator()
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
separator()
# for numPoints in testNumPoints:
# let batchIters = max(1, Iters div numPoints)
# msmBench(ECP_ShortW_Prj[Fp[curve], G1], numPoints, batchIters)
# separator()
# separator()
for numPoints in testNumPoints:
let batchIters = max(1, Iters div numPoints)
msmBench(ECP_ShortW_Jac[Fp[curve], G1], numPoints, batchIters)
separator()
separator()

main()
notes()
81 changes: 81 additions & 0 deletions benchmarks/bench_ec_g1_scalar_mul.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.

import
# Internals
../constantine/math/config/curves,
../constantine/math/arithmetic,
../constantine/math/elliptic/[
ec_shortweierstrass_projective,
ec_shortweierstrass_jacobian],
# Helpers
./bench_elliptic_template

# ############################################################
#
# Benchmark of the G1 group of
# Short Weierstrass elliptic curves
# in (homogeneous) projective coordinates
#
# ############################################################


const Iters = 10_000
const MulIters = 100
const AvailableCurves = [
# P224,
BN254_Nogami,
BN254_Snarks,
# Edwards25519,
# P256,
# Secp256k1,
Pallas,
Vesta,
BLS12_377,
BLS12_381,
]

proc main() =
separator()
staticFor i, 0, AvailableCurves.len:
const curve = AvailableCurves[i]
const bits = 64 # curve.getCurveOrderBitwidth()
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Prj[Fp[curve], G1], bits, MulIters)
scalarMulUnsafeDoubleAddBench(ECP_ShortW_Jac[Fp[curve], G1], bits, MulIters)
separator()
scalarMulUnsafeMinHammingWeightRecodingBench(ECP_ShortW_Prj[Fp[curve], G1], bits, MulIters)
scalarMulUnsafeMinHammingWeightRecodingBench(ECP_ShortW_Jac[Fp[curve], G1], bits, MulIters)
separator()
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 5, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 2, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 3, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 4, MulIters)
scalarMulGenericBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 5, MulIters)
separator()
scalarMulUnsafeWNAFBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 2, MulIters)
scalarMulUnsafeWNAFBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 3, MulIters)
scalarMulUnsafeWNAFBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 4, MulIters)
scalarMulUnsafeWNAFBench(ECP_ShortW_Prj[Fp[curve], G1], bits, window = 5, MulIters)
scalarMulUnsafeWNAFBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 2, MulIters)
scalarMulUnsafeWNAFBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 3, MulIters)
scalarMulUnsafeWNAFBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 4, MulIters)
scalarMulUnsafeWNAFBench(ECP_ShortW_Jac[Fp[curve], G1], bits, window = 5, MulIters)
separator()
when bits >= 196: # All endomorphisms constants are below this threshold
scalarMulEndo( ECP_ShortW_Prj[Fp[curve], G1], bits, MulIters)
scalarMulEndoWindow(ECP_ShortW_Prj[Fp[curve], G1], bits, MulIters)
scalarMulEndo( ECP_ShortW_Jac[Fp[curve], G1], bits, MulIters)
scalarMulEndoWindow(ECP_ShortW_Jac[Fp[curve], G1], bits, MulIters)
separator()
separator()

main()
notes()
Loading