Skip to content

Commit

Permalink
perf: fast path for SIS with logTwoBound: 8, logTwoDegree: 6 (#416)
Browse files Browse the repository at this point in the history
* perf: add unrolled FFT for sis

* perf: fast limb decomposition for known params

* test: push failing test

* fix: fix hardcoded limb decomposition and its test

* fix: make linter happier

* tmp commit

* tmp commit

* cleaning up

* perf: put all twiddle coset in consecutive memory

* fix: re ran go generate

* test: uncomment commented test
  • Loading branch information
gbotrel authored Jun 30, 2023
1 parent ce693dc commit cf1c8bd
Show file tree
Hide file tree
Showing 19 changed files with 66,495 additions and 65,856 deletions.
3 changes: 1 addition & 2 deletions ecc/bls12-377/fr/fft/fft.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions ecc/bls12-378/fr/fft/fft.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions ecc/bls12-381/fr/fft/fft.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions ecc/bls24-315/fr/fft/fft.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions ecc/bls24-317/fr/fft/fft.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions ecc/bn254/fr/fft/fft.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 41 additions & 6 deletions ecc/bn254/fr/sis/sis.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ type RSis struct {
LogTwoBound int

// domain for the polynomial multiplication
Domain *fft.Domain
Domain *fft.Domain
twiddleCosets []fr.Element // see fft64 and precomputeTwiddlesCoset

// d, the degree of X^{d}+1
Degree int
Expand Down Expand Up @@ -126,6 +127,10 @@ func NewRSis(seed int64, logTwoDegree, logTwoBound, maxNbElementsToHash int) (*R
bufMValues: bitset.New(uint(n)),
maxNbElementsToHash: maxNbElementsToHash,
}
if r.LogTwoBound == 8 && r.Degree == 64 {
// TODO @gbotrel fixme, that's dirty.
r.twiddleCosets = precomputeTwiddlesCoset(r.Domain.Twiddles, r.Domain.FrMultiplicativeGen)
}

// filling A
a := make([]fr.Element, n*r.Degree)
Expand All @@ -146,8 +151,6 @@ func NewRSis(seed int64, logTwoDegree, logTwoBound, maxNbElementsToHash int) (*R
r.Domain.FFT(r.Ag[i], fft.DIF, fft.OnCoset())
}
})
// TODO @gbotrel add nbtasks here; while in tests it's more convenient to parallelize
// in tensor-commitment we may not want to do that.

return r, nil
}
Expand All @@ -168,12 +171,20 @@ func (r *RSis) Sum(b []byte) []byte {
panic("buffer too large")
}

fastPath := r.LogTwoBound == 8 && r.Degree == 64

// clear the buffers of the instance.
defer r.cleanupBuffers()

m := r.bufM
mValues := r.bufMValues
limbDecomposeBytes(buf, m, r.LogTwoBound, r.Degree, mValues)

if fastPath {
// fast path.
limbDecomposeBytes8_64(buf, m, mValues)
} else {
limbDecomposeBytes(buf, m, r.LogTwoBound, r.Degree, mValues)
}

// we can hash now.
res := r.bufRes
Expand All @@ -186,7 +197,12 @@ func (r *RSis) Sum(b []byte) []byte {
continue
}
k := m[i*r.Degree : (i+1)*r.Degree]
r.Domain.FFT(k, fft.DIF, fft.OnCoset(), fft.WithNbTasks(1))
if fastPath {
// fast path.
fft64(k, r.twiddleCosets)
} else {
r.Domain.FFT(k, fft.DIF, fft.OnCoset(), fft.WithNbTasks(1))
}
mulModAcc(res, r.Ag[i], k)
}
r.Domain.FFTInverse(res, fft.DIT, fft.OnCoset(), fft.WithNbTasks(1)) // -> reduces mod Xᵈ+1
Expand Down Expand Up @@ -357,11 +373,12 @@ func limbDecomposeBytes(buf []byte, m fr.Vector, logTwoBound, degree int, mValue
// r.LogTwoBound < 64; we just use the first word of our element here,
// and set the bits from LSB to MSB.
at := fieldStart + fr.Bytes*8 - bitInField - 1

m[mPos][0] |= uint64(bitAt(at) << j)
bitInField++

// Check if mPos is zero and mark as non-zero in the bitset if not
if m[mPos][0] > 0 && mValues != nil {
if m[mPos][0] != 0 && mValues != nil {
mValues.Set(uint(mPos / degree))
}

Expand All @@ -372,3 +389,21 @@ func limbDecomposeBytes(buf []byte, m fr.Vector, logTwoBound, degree int, mValue
fieldStart += fr.Bytes * 8
}
}

// see limbDecomposeBytes; this function is optimized for the case where
// logTwoBound == 8 and degree == 64
func limbDecomposeBytes8_64(buf []byte, m fr.Vector, mValues *bitset.BitSet) {
// with logTwoBound == 8, we can actually advance byte per byte.
const degree = 64
j := 0

for startPos := fr.Bytes - 1; startPos < len(buf); startPos += fr.Bytes {
for i := startPos; i >= startPos-fr.Bytes+1; i-- {
m[j][0] = uint64(buf[i])
if m[j][0] != 0 {
mValues.Set(uint(j / degree))
}
j++
}
}
}
1 change: 1 addition & 0 deletions ecc/bn254/fr/sis/sis.sage
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ params = [
SISParams(5, 4, 4, 10),
SISParams(5, 5, 4, 10),
SISParams(5, 6, 5, 10),
# SISParams(5, 8, 6, 10),
SISParams(5, 10, 6, 10),
SISParams(5, 11, 7, 10),
SISParams(5, 12, 7, 10),
Expand Down
Loading

0 comments on commit cf1c8bd

Please sign in to comment.