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

Seemingly needless clearing of array values #529

Closed
holiman opened this issue Aug 27, 2024 · 3 comments · Fixed by #530
Closed

Seemingly needless clearing of array values #529

holiman opened this issue Aug 27, 2024 · 3 comments · Fixed by #530

Comments

@holiman
Copy link

holiman commented Aug 27, 2024

Looking at the code here: https://github.com/Consensys/gnark-crypto/blob/master/ecc/bls12-381/multiexp_jacobian.go#L108

func processChunkG2Jacobian[B ibg2JacExtended](chunk uint64,
	chRes chan<- g2JacExtended,
	c uint64,
	points []G2Affine,
	digits []uint16,
	sem chan struct{}) {

	if sem != nil {
		// if we are limited, wait for a token in the semaphore
		<-sem
	}

	var buckets B
	for i := 0; i < len(buckets); i++ {
		buckets[i].setInfinity()
	}

The code waits for a go-ahead, to start processing the items. The wait, I presume, is to ensure that the worker doesn't interfere with other threads, or maybe that the inputs are not ready yet.

However, the local variable buckets is not shared, and thus it should be perfectly ok to do the buckets[i].setInfinity()-loop before waiting for the <-sem.

Looking into it a bit deeper, however, I see that the buckets is a newly stack-allocated array of g2JacExtended. For example, it might be [32]g2JacExtended.

The g2JacExtended is:

type g2JacExtended struct {
	X, Y, ZZ, ZZZ fptower.E2
}

and the setInfinity() is

func (p *G2Affine) setInfinity() *G2Affine {
	p.X.SetZero()
	p.Y.SetZero()
	return p
}

As far as I can tell, the setInfinity -> SetZero methods, in the end, boil down to zeroing uint64-arrays. This is not necessary in golang, newly allocated arrays (heap or stack) are always zeroed.

So afaict the buckets[i].setInfinity()-loop can just be dropped. Perhaps I am missing something?

@holiman
Copy link
Author

holiman commented Aug 27, 2024

Ah, it seems that g1JacExtended are already at inifinity (zeroed) at construction, whereas g2JacExtended are not at infinity when zero. So e.g. this is actually required:

	var runningSum, total g2JacExtended
	runningSum.setInfinity()
	total.setInfinity()

(but the buckets should still be fine from the get-go)

@ivokub
Copy link
Collaborator

ivokub commented Aug 27, 2024

cc. @gbotrel, but it seems right that for G1 methods we can avoid zeroing the buckets.

@gbotrel
Copy link
Collaborator

gbotrel commented Aug 27, 2024

yes indeed, we can avoid zeroing the buckets twice with the affine msm. I suspect the code is here because some previous iterations had the buckets in extended jacobian coordinates; don't think it's going to be visible on benchmarks though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants
@holiman @ivokub @gbotrel and others