mirror of
https://github.com/tornadocash/websnark.git
synced 2024-11-23 18:32:55 +01:00
Optimization of the int_mul code
This commit is contained in:
parent
6c5cf8d4e5
commit
4e6f320667
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -35,7 +35,17 @@ function calcProof() {
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
function test(funcName, a, b, r, n) {
|
||||
|
||||
const start = new Date().getTime();
|
||||
window.groth16.instance.exports[funcName](a,b,r, n);
|
||||
const end = new Date().getTime();
|
||||
const time = end - start;
|
||||
|
||||
console.log("Time (ms): " + time);
|
||||
}
|
||||
|
||||
function test2() {
|
||||
|
||||
const groth16 = window.groth16;
|
||||
const nSignals = 1;
|
||||
|
File diff suppressed because one or more lines are too long
101
src/build_int.js
101
src/build_int.js
@ -284,9 +284,106 @@ module.exports = function buildInt(module, n64, _prefix) {
|
||||
|
||||
function buildMul() {
|
||||
|
||||
const f = module.addFunction(prefix+"_mul");
|
||||
f.addParam("x", "i32");
|
||||
f.addParam("y", "i32");
|
||||
f.addParam("r", "i32");
|
||||
f.addLocal("c0", "i64");
|
||||
f.addLocal("c1", "i64");
|
||||
|
||||
|
||||
for (let i=0;i<n32; i++) {
|
||||
f.addLocal("x"+i, "i64");
|
||||
f.addLocal("y"+i, "i64");
|
||||
}
|
||||
|
||||
const c = f.getCodeBuilder();
|
||||
|
||||
const loadX = [];
|
||||
const loadY = [];
|
||||
function mulij(i, j) {
|
||||
let X,Y;
|
||||
if (!loadX[i]) {
|
||||
X = c.teeLocal("x"+i, c.i64_load32_u( c.getLocal("x"), i*4));
|
||||
loadX[i] = true;
|
||||
} else {
|
||||
X = c.getLocal("x"+i);
|
||||
}
|
||||
if (!loadY[j]) {
|
||||
Y = c.teeLocal("y"+j, c.i64_load32_u( c.getLocal("y"), j*4));
|
||||
loadY[j] = true;
|
||||
} else {
|
||||
Y = c.getLocal("y"+j);
|
||||
}
|
||||
|
||||
return c.i64_mul( X, Y );
|
||||
}
|
||||
|
||||
let c0 = "c0";
|
||||
let c1 = "c1";
|
||||
|
||||
for (let k=0; k<n32*2-1; k++) {
|
||||
for (let i=Math.max(0, k-n32+1); (i<=k)&&(i<n32); i++) {
|
||||
const j= k-i;
|
||||
|
||||
f.addCode(
|
||||
c.setLocal(c0,
|
||||
c.i64_add(
|
||||
c.i64_and(
|
||||
c.getLocal(c0),
|
||||
c.i64_const(0xFFFFFFFF)
|
||||
),
|
||||
mulij(i,j)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
f.addCode(
|
||||
c.setLocal(c1,
|
||||
c.i64_add(
|
||||
c.getLocal(c1),
|
||||
c.i64_shr_u(
|
||||
c.getLocal(c0),
|
||||
c.i64_const(32)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
f.addCode(
|
||||
c.i64_store32(
|
||||
c.getLocal("r"),
|
||||
k*4,
|
||||
c.getLocal(c0)
|
||||
)
|
||||
);
|
||||
[c0, c1] = [c1, c0];
|
||||
f.addCode(
|
||||
c.setLocal(c1,
|
||||
c.i64_shr_u(
|
||||
c.getLocal(c0),
|
||||
c.i64_const(32)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
f.addCode(
|
||||
c.i64_store32(
|
||||
c.getLocal("r"),
|
||||
n32*4*2-4,
|
||||
c.getLocal(c0)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function buildMulOld() {
|
||||
|
||||
const mulBuff = module.alloc(n32*n32*8);
|
||||
|
||||
const f = module.addFunction(prefix+"_mul");
|
||||
const f = module.addFunction(prefix+"_mulOld");
|
||||
f.addParam("x", "i32");
|
||||
f.addParam("y", "i32");
|
||||
f.addParam("r", "i32");
|
||||
@ -843,6 +940,7 @@ module.exports = function buildInt(module, n64, _prefix) {
|
||||
buildAdd();
|
||||
buildSub();
|
||||
buildMul();
|
||||
buildMulOld();
|
||||
buildDiv();
|
||||
buildInverseMod();
|
||||
module.exportFunction(prefix+"_copy");
|
||||
@ -853,6 +951,7 @@ module.exports = function buildInt(module, n64, _prefix) {
|
||||
module.exportFunction(prefix+"_gte");
|
||||
module.exportFunction(prefix+"_add");
|
||||
module.exportFunction(prefix+"_sub");
|
||||
module.exportFunction(prefix+"_mulOld");
|
||||
module.exportFunction(prefix+"_mul");
|
||||
module.exportFunction(prefix+"_div");
|
||||
module.exportFunction(prefix+"_inverseMod");
|
||||
|
23
src/build_test.js
Normal file
23
src/build_test.js
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
function buildTest(module, fn) {
|
||||
const f = module.addFunction("test_"+fn);
|
||||
f.addParam("x", "i32");
|
||||
f.addParam("y", "i32");
|
||||
f.addParam("r", "i32");
|
||||
f.addParam("n", "i32");
|
||||
f.addLocal("i", "i32");
|
||||
|
||||
const c = f.getCodeBuilder();
|
||||
|
||||
f.addCode(c.setLocal("i", c.getLocal("n")));
|
||||
f.addCode(c.block(c.loop(
|
||||
c.call(fn, c.getLocal("x"), c.getLocal("y"), c.getLocal("r")),
|
||||
c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))),
|
||||
c.br_if(1, c.i32_eqz ( c.getLocal("i") )),
|
||||
c.br(0)
|
||||
)));
|
||||
|
||||
module.exportFunction("test_"+fn);
|
||||
}
|
||||
|
||||
module.exports = buildTest;
|
25
test/helpers/helpers.js
Normal file
25
test/helpers/helpers.js
Normal file
@ -0,0 +1,25 @@
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
function genValues(n, neg, bitsPerWord) {
|
||||
bitsPerWord = bitsPerWord || 32;
|
||||
const res = [];
|
||||
res.push(bigInt.zero);
|
||||
for (let i=0; i<n; i++) {
|
||||
if (i>0) {
|
||||
res.push( bigInt.one.shiftLeft(bitsPerWord*i).minus(1));
|
||||
}
|
||||
if (i<n-1) {
|
||||
res.push( bigInt.one.shiftLeft(bitsPerWord*i));
|
||||
res.push( bigInt.one.shiftLeft(bitsPerWord*i).add(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
const nt= res.length;
|
||||
for (let i=0; i<nt; i++) res.push(bigInt.zero.minus(res[i]));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
module.exports.genValues = genValues;
|
84
test/int.js
Normal file
84
test/int.js
Normal file
@ -0,0 +1,84 @@
|
||||
const assert = require("assert");
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
const buildProtoboard = require("../src/protoboard.js");
|
||||
const buildInt = require("../src/build_int.js");
|
||||
const buildTest = require("../src/build_test.js");
|
||||
|
||||
const helpers = require("./helpers/helpers.js");
|
||||
|
||||
|
||||
describe("Basic tests for Int", () => {
|
||||
let pbInt;
|
||||
|
||||
before(async () => {
|
||||
pbInt = await buildProtoboard((module) => {
|
||||
buildInt(module, 4);
|
||||
buildTest(module, "int_mul");
|
||||
buildTest(module, "int_mulOld");
|
||||
}, 32);
|
||||
});
|
||||
|
||||
it("It should do a basic multiplication", async () => {
|
||||
let c;
|
||||
const pA = pbInt.alloc();
|
||||
const pB = pbInt.alloc();
|
||||
const pC = pbInt.alloc(64);
|
||||
|
||||
const values = helpers.genValues(8, false);
|
||||
|
||||
for (let i=0; i<values.length; i++) {
|
||||
for (let j=0; j<values.length; j++) {
|
||||
pbInt.set(pA, values[i]);
|
||||
pbInt.set(pB, values[j]);
|
||||
// console.log(values[i].toString(16));
|
||||
// console.log(values[j].toString(16));
|
||||
|
||||
pbInt.int_mul(pA, pB, pC);
|
||||
c = pbInt.get(pC, 1, 64);
|
||||
|
||||
// console.log("Result: " + c.toString(16));
|
||||
// console.log("Refere: " + values[i].times(values[j]).toString(16));
|
||||
assert(c.equals(values[i].times(values[j])));
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("It should profile int", async () => {
|
||||
|
||||
const pA = pbInt.alloc();
|
||||
const pB = pbInt.alloc();
|
||||
const pC = pbInt.alloc(64);
|
||||
|
||||
let start, end, time;
|
||||
|
||||
const A = bigInt.one.shiftLeft(256).minus(1);
|
||||
const B = bigInt.one.shiftLeft(256).minus(1);
|
||||
|
||||
pbInt.set(pA, A);
|
||||
pbInt.set(pB, B);
|
||||
|
||||
start = new Date().getTime();
|
||||
pbInt.test_int_mul(pA, pB, pC, 50000000);
|
||||
end = new Date().getTime();
|
||||
time = end - start;
|
||||
|
||||
const c1 = pbInt.get(pC, 1, 64);
|
||||
assert(c1.equals(A.times(B)));
|
||||
|
||||
console.log("Mul Time (ms): " + time);
|
||||
|
||||
start = new Date().getTime();
|
||||
pbInt.test_int_mulOld(pA, pB, pC, 50000000);
|
||||
end = new Date().getTime();
|
||||
time = end - start;
|
||||
|
||||
const c2 = pbInt.get(pC, 1, 64);
|
||||
assert(c2.equals(A.times(B)));
|
||||
|
||||
console.log("Mul Old Time (ms): " + time);
|
||||
|
||||
}).timeout(10000000);
|
||||
|
||||
});
|
@ -4,49 +4,11 @@ const bigInt = require("big-integer");
|
||||
const buildProtoboard = require("../src/protoboard.js");
|
||||
const buildTomCook = require("../src/build_tomcook.js");
|
||||
const buildInt = require("../src/build_int.js");
|
||||
const buildTest = require("../src/build_test.js");
|
||||
|
||||
const helpers = require("./helpers/helpers.js");
|
||||
|
||||
|
||||
function buildTest(module, fn) {
|
||||
const f = module.addFunction("test_"+fn);
|
||||
f.addParam("x", "i32");
|
||||
f.addParam("y", "i32");
|
||||
f.addParam("r", "i32");
|
||||
f.addParam("n", "i32");
|
||||
f.addLocal("i", "i32");
|
||||
|
||||
const c = f.getCodeBuilder();
|
||||
|
||||
f.addCode(c.setLocal("i", c.getLocal("n")));
|
||||
f.addCode(c.block(c.loop(
|
||||
c.call(fn, c.getLocal("x"), c.getLocal("y"), c.getLocal("r")),
|
||||
c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))),
|
||||
c.br_if(1, c.i32_eqz ( c.getLocal("i") )),
|
||||
c.br(0)
|
||||
)));
|
||||
|
||||
module.exportFunction("test_"+fn);
|
||||
}
|
||||
|
||||
function genValues(n, neg) {
|
||||
const res = [];
|
||||
res.push(bigInt.zero);
|
||||
for (let i=0; i<n; i++) {
|
||||
if (i>0) {
|
||||
res.push( bigInt.one.shiftLeft(29*i).minus(1));
|
||||
}
|
||||
if (i<8) {
|
||||
res.push( bigInt.one.shiftLeft(29*i));
|
||||
res.push( bigInt.one.shiftLeft(29*i).add(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
const nt= res.length;
|
||||
for (let i=0; i<nt; i++) res.push(bigInt.zero.minus(res[i]));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
let pbTC;
|
||||
@ -67,7 +29,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
let c;
|
||||
const pA = pbTC.alloc(6*4);
|
||||
|
||||
const values = genValues(6, true);
|
||||
const values = helpers.genValues(6, true, 29);
|
||||
|
||||
for (let i=0; i<values.length; i++) {
|
||||
pbTC.set(pA, values[i], 24);
|
||||
@ -81,7 +43,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
let c;
|
||||
const pA = pbTC.alloc(6*4);
|
||||
|
||||
const values = genValues(6, true);
|
||||
const values = helpers.genValues(6, true, 29);
|
||||
|
||||
for (let i=0; i<values.length; i++) {
|
||||
pbTC.set(pA, values[i], 24);
|
||||
@ -96,7 +58,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
let c;
|
||||
const pA = pbTC.alloc(6*4);
|
||||
|
||||
const values = genValues(6, true);
|
||||
const values = helpers.genValues(6, true, 29);
|
||||
|
||||
for (let i=0; i<values.length; i++) {
|
||||
// console.log(values[i].toString(16));
|
||||
@ -114,7 +76,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
const pB = pbTC.alloc();
|
||||
const pC = pbTC.alloc(24);
|
||||
|
||||
const values = genValues(3, true);
|
||||
const values = helpers.genValues(3, true, 29);
|
||||
|
||||
for (let i=0; i<values.length; i++) {
|
||||
for (let j=0; j<values.length; j++) {
|
||||
@ -164,7 +126,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
const pB = pbTC.alloc(9*4);
|
||||
const pC = pbTC.alloc(9*4*2);
|
||||
|
||||
const values = genValues(9, false);
|
||||
const values = helpers.genValues(9, false, 29);
|
||||
|
||||
for (let i=0; i<values.length; i++) {
|
||||
for (let j=0; j<values.length; j++) {
|
||||
@ -186,6 +148,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it("It should profile school", async () => {
|
||||
const A = bigInt.one.shiftLeft(254).minus(1);
|
||||
const B = bigInt.one.shiftLeft(254).minus(1);
|
||||
@ -195,7 +158,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
const pC = pbInt.alloc(64);
|
||||
|
||||
const start = new Date().getTime();
|
||||
pbInt.test_int_mul(pA, pB, pC, 100000000);
|
||||
pbInt.test_int_mul(pA, pB, pC, 10000000);
|
||||
const end = new Date().getTime();
|
||||
const time = end - start;
|
||||
|
||||
@ -225,7 +188,7 @@ describe("Basic tests for Tom Cook Multiplication Strategy", () => {
|
||||
// console.log("Mul1 Tom Cook Time (ms): " + time);
|
||||
|
||||
start = new Date().getTime();
|
||||
pbTC.test_tomcook_mul9(pA, pB, pC, 100000000);
|
||||
pbTC.test_tomcook_mul9(pA, pB, pC, 10000000);
|
||||
end = new Date().getTime();
|
||||
time = end - start;
|
||||
|
||||
|
@ -4,10 +4,10 @@ const buildF1m = require("../src/build_f1m.js");
|
||||
const buildF2m = require("../src/build_f2m.js");
|
||||
const buildF1 = require("../src/build_f1.js");
|
||||
const buildCurve = require("../src/build_curve.js");
|
||||
const buildTest = require("../src/build_testg1");
|
||||
const buildFFT = require("../src/build_fft");
|
||||
const buildMultiexp = require("../src/build_multiexp");
|
||||
const buildPol = require("../src/build_pol");
|
||||
const buildTest = require("../src/build_test");
|
||||
const utils = require("../src/utils");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
@ -37,7 +37,8 @@ function buildWasm() {
|
||||
buildCurve(moduleBuilder, "g2", "f2m");
|
||||
buildMultiexp(moduleBuilder, "g2", "g2", "f2m", "fr");
|
||||
|
||||
buildTest(moduleBuilder);
|
||||
buildTest(moduleBuilder, "int_mul");
|
||||
buildTest(moduleBuilder, "int_mulOld");
|
||||
|
||||
const code = moduleBuilder.build();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user