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

Endomorphism acceleration for Scalar Multiplication #44

Merged
merged 19 commits into from
Jun 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ proc main() =
separator()
doublingBench(ECP_SWei_Proj[Fp[curve]], Iters)
separator()
scalarMulBench(ECP_SWei_Proj[Fp[curve]], scratchSpaceSize = 1 shl 2, MulIters)
scalarMulUnsafeDoubleAddBench(ECP_SWei_Proj[Fp[curve]], MulIters)
separator()
scalarMulBench(ECP_SWei_Proj[Fp[curve]], scratchSpaceSize = 1 shl 3, MulIters)
scalarMulGenericBench(ECP_SWei_Proj[Fp[curve]], scratchSpaceSize = 1 shl 2, MulIters)
separator()
scalarMulBench(ECP_SWei_Proj[Fp[curve]], scratchSpaceSize = 1 shl 4, MulIters)
scalarMulGenericBench(ECP_SWei_Proj[Fp[curve]], scratchSpaceSize = 1 shl 3, MulIters)
separator()
scalarMulGenericBench(ECP_SWei_Proj[Fp[curve]], scratchSpaceSize = 1 shl 4, MulIters)
separator()
scalarMulGLV(ECP_SWei_Proj[Fp[curve]], MulIters)
separator()
# scalarMulUnsafeDoubleAddBench(ECP_SWei_Proj[Fp[curve]], MulIters)
# separator()
separator()

main()
Expand Down
59 changes: 36 additions & 23 deletions benchmarks/bench_elliptic_template.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ import
../constantine/config/curves,
../constantine/arithmetic,
../constantine/io/io_bigints,
../constantine/elliptic/[ec_weierstrass_projective, ec_scalar_mul, ec_endomorphism_accel],
# Helpers
../helpers/[prng_unsafe, static_for],
./platforms,
# Standard library
std/[monotimes, times, strformat, strutils, macros]
std/[monotimes, times, strformat, strutils, macros],
# Reference unsafe scalar multiplication
../tests/support/ec_reference_scalar_mult

var rng: RngState
let seed = uint32(getTime().toUnix() and (1'i64 shl 32 - 1)) # unixTime mod 2^32
Expand Down Expand Up @@ -71,15 +74,15 @@ when SupportsGetTicks:
echo "\n=================================================================================================================\n"

proc separator*() =
echo "-".repeat(157)
echo "-".repeat(177)

proc report(op, elliptic: string, start, stop: MonoTime, startClk, stopClk: int64, iters: int) =
let ns = inNanoseconds((stop-start) div iters)
let throughput = 1e9 / float64(ns)
when SupportsGetTicks:
echo &"{op:<40} {elliptic:<40} {throughput:>15.3f} ops/s {ns:>9} ns/op {(stopClk - startClk) div iters:>9} CPU cycles (approx)"
echo &"{op:<60} {elliptic:<40} {throughput:>15.3f} ops/s {ns:>9} ns/op {(stopClk - startClk) div iters:>9} CPU cycles (approx)"
else:
echo &"{op:<40} {elliptic:<40} {throughput:>15.3f} ops/s {ns:>9} ns/op"
echo &"{op:<60} {elliptic:<40} {throughput:>15.3f} ops/s {ns:>9} ns/op"

macro fixEllipticDisplay(T: typedesc): untyped =
# At compile-time, enums are integers and their display is buggy
Expand Down Expand Up @@ -120,34 +123,44 @@ proc doublingBench*(T: typedesc, iters: int) =
bench("EC Double G1", T, iters):
r.double(P)

proc scalarMulBench*(T: typedesc, scratchSpaceSize: static int, iters: int) =
proc scalarMulGenericBench*(T: typedesc, scratchSpaceSize: static int, iters: int) =
const bits = T.F.C.getCurveOrderBitwidth()

var r {.noInit.}: T
let P = rng.random_unsafe(T)
let P = rng.random_unsafe(T) # TODO: clear cofactor

let exponent = rng.random_unsafe(BigInt[bits])
var exponentCanonical{.noInit.}: array[(bits+7) div 8, byte]
exponentCanonical.exportRawUint(exponent, bigEndian)

var scratchSpace{.noInit.}: array[scratchSpaceSize, T]

bench("EC ScalarMul G1 (scratchsize = " & $scratchSpaceSize & ')', T, iters):
bench("EC ScalarMul Generic G1 (scratchsize = " & $scratchSpaceSize & ')', T, iters):
r = P
r.scalarMul(exponentCanonical, scratchSpace)
r.scalarMulGeneric(exponentCanonical, scratchSpace)

# import ../tests/support/ec_reference_scalar_mult
#
# proc scalarMulUnsafeDoubleAddBench*(T: typedesc, iters: int) =
# const bits = T.F.C.getCurveOrderBitwidth()
#
# var r {.noInit.}: T
# let P = rng.random_unsafe(T)
#
# let exponent = rng.random_unsafe(BigInt[bits])
# var exponentCanonical{.noInit.}: array[(bits+7) div 8, byte]
# exponentCanonical.exportRawUint(exponent, bigEndian)
#
# bench("EC ScalarMul G1 (unsafe DoubleAdd)", T, iters):
# r = P
# r.unsafe_ECmul_double_add(exponentCanonical)
proc scalarMulGLV*(T: typedesc, iters: int) =
const bits = T.F.C.getCurveOrderBitwidth()

var r {.noInit.}: T
let P = rng.random_unsafe(T) # TODO: clear cofactor

let exponent = rng.random_unsafe(BigInt[bits])

bench("EC ScalarMul G1 (GLV endomorphism accelerated)", T, iters):
r = P
r.scalarMulGLV(exponent)

proc scalarMulUnsafeDoubleAddBench*(T: typedesc, iters: int) =
const bits = T.F.C.getCurveOrderBitwidth()

var r {.noInit.}: T
let P = rng.random_unsafe(T) # TODO: clear cofactor

let exponent = rng.random_unsafe(BigInt[bits])
var exponentCanonical{.noInit.}: array[(bits+7) div 8, byte]
exponentCanonical.exportRawUint(exponent, bigEndian)

bench("EC ScalarMul G1 (unsafe reference DoubleAdd)", T, iters):
r = P
r.unsafe_ECmul_double_add(exponentCanonical)
40 changes: 27 additions & 13 deletions constantine.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ task test, "Run all tests":
test "", "tests/test_bigints.nim"
test "", "tests/test_bigints_multimod.nim"

test "", "tests/test_bigints_vs_gmp.nim"
test "", "tests/test_bigints_mod_vs_gmp.nim"

# Field
test "", "tests/test_io_fields"
Expand All @@ -70,6 +70,9 @@ task test, "Run all tests":

test "", "tests/test_finite_fields_vs_gmp.nim"

# Precompute
test "", "tests/test_precomputed"

# Towers of extension fields
test "", "tests/test_fp2.nim"
test "", "tests/test_fp6.nim"
Expand All @@ -89,7 +92,7 @@ task test, "Run all tests":
test "-d:Constantine32", "tests/test_bigints.nim"
test "-d:Constantine32", "tests/test_bigints_multimod.nim"

test "-d:Constantine32", "tests/test_bigints_vs_gmp.nim"
test "-d:Constantine32", "tests/test_bigints_mod_vs_gmp.nim"

# Field
test "-d:Constantine32", "tests/test_io_fields"
Expand All @@ -100,6 +103,9 @@ task test, "Run all tests":

test "-d:Constantine32", "tests/test_finite_fields_vs_gmp.nim"

# Precompute
test "-d:Constantine32", "tests/test_precomputed"

# Towers of extension fields
test "-d:Constantine32", "tests/test_fp2.nim"
test "-d:Constantine32", "tests/test_fp6.nim"
Expand All @@ -118,7 +124,7 @@ task test, "Run all tests":
runBench("bench_fp2")
runBench("bench_fp6")
runBench("bench_fp12")
runBench("bench_ec_swei_proj_g1")
runBench("bench_ec_g1")

task test_no_gmp, "Run tests that don't require GMP":
# -d:testingCurves is configured in a *.nim.cfg for convenience
Expand All @@ -138,6 +144,9 @@ task test_no_gmp, "Run tests that don't require GMP":
test "", "tests/test_finite_fields_sqrt.nim"
test "", "tests/test_finite_fields_powinv.nim"

# Precompute
test "", "tests/test_precomputed"

# Towers of extension fields
test "", "tests/test_fp2.nim"
test "", "tests/test_fp6.nim"
Expand All @@ -164,6 +173,9 @@ task test_no_gmp, "Run tests that don't require GMP":
test "-d:Constantine32", "tests/test_finite_fields_sqrt.nim"
test "-d:Constantine32", "tests/test_finite_fields_powinv.nim"

# Precompute
test "-d:Constantine32", "tests/test_precomputed"

# Towers of extension fields
test "-d:Constantine32", "tests/test_fp2.nim"
test "-d:Constantine32", "tests/test_fp6.nim"
Expand All @@ -182,7 +194,7 @@ task test_no_gmp, "Run tests that don't require GMP":
runBench("bench_fp2")
runBench("bench_fp6")
runBench("bench_fp12")
runBench("bench_ec_swei_proj_g1")
runBench("bench_ec_g1")

task test_parallel, "Run all tests in parallel (via GNU parallel)":
# -d:testingCurves is configured in a *.nim.cfg for convenience
Expand All @@ -197,7 +209,8 @@ task test_parallel, "Run all tests in parallel (via GNU parallel)":
test "", "tests/test_bigints.nim", cmdFile
test "", "tests/test_bigints_multimod.nim", cmdFile

test "", "tests/test_bigints_vs_gmp.nim", cmdFile
test "", "tests/test_bigints_mul_vs_gmp.nim", cmdFile
test "", "tests/test_bigints_mod_vs_gmp.nim", cmdFile

# Field
test "", "tests/test_io_fields", cmdFile
Expand Down Expand Up @@ -233,7 +246,8 @@ task test_parallel, "Run all tests in parallel (via GNU parallel)":
test "-d:Constantine32", "tests/test_bigints.nim", cmdFile
test "-d:Constantine32", "tests/test_bigints_multimod.nim", cmdFile

test "-d:Constantine32", "tests/test_bigints_vs_gmp.nim", cmdFile
test "-d:Constantine32", "tests/test_bigints_mul_vs_gmp.nim", cmdFile
test "-d:Constantine32", "tests/test_bigints_mod_vs_gmp.nim", cmdFile

# Field
test "-d:Constantine32", "tests/test_io_fields", cmdFile
Expand Down Expand Up @@ -268,7 +282,7 @@ task test_parallel, "Run all tests in parallel (via GNU parallel)":
runBench("bench_fp2")
runBench("bench_fp6")
runBench("bench_fp12")
runBench("bench_ec_swei_proj_g1")
runBench("bench_ec_g1")

task bench_fp, "Run benchmark 𝔽p with your default compiler":
runBench("bench_fp")
Expand Down Expand Up @@ -306,11 +320,11 @@ task bench_fp12_gcc, "Run benchmark 𝔽p12 with gcc":
task bench_fp12_clang, "Run benchmark 𝔽p12 with clang":
runBench("bench_fp12", "clang")

task bench_ec_swei_proj_g1, "Run benchmark on Elliptic Curve group 𝔾1 - Short Weierstrass with Projective Coordinates - GCC":
runBench("bench_ec_swei_proj_g1")
task bench_ec_g1, "Run benchmark on Elliptic Curve group 𝔾1 - Short Weierstrass with Projective Coordinates - GCC":
runBench("bench_ec_g1")

task bench_ec_swei_proj_g1_gcc, "Run benchmark on Elliptic Curve group 𝔾1 - Short Weierstrass with Projective Coordinates - GCC":
runBench("bench_ec_swei_proj_g1", "gcc")
task bench_ec_gcc, "Run benchmark on Elliptic Curve group 𝔾1 - Short Weierstrass with Projective Coordinates - GCC":
runBench("bench_ec_g1", "gcc")

task bench_ec_swei_proj_g1_clang, "Run benchmark on Elliptic Curve group 𝔾1 - Short Weierstrass with Projective Coordinates - Clang":
runBench("bench_ec_swei_proj_g1", "clang")
task bench_ec_g1_clang, "Run benchmark on Elliptic Curve group 𝔾1 - Short Weierstrass with Projective Coordinates - Clang":
runBench("bench_ec_g1", "clang")
2 changes: 0 additions & 2 deletions constantine/arithmetic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.

import
arithmetic/[limbs, limbs_modular, limbs_montgomery],
arithmetic/bigints,
arithmetic/[finite_fields, finite_fields_inversion]

export
limbs, limbs_modular, limbs_montgomery,
bigints,
finite_fields, finite_fields_inversion
Loading