-
Notifications
You must be signed in to change notification settings - Fork 405
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
FEAT: Add experimental support for Icicle GPU acceleration behind build tag #844
Conversation
…th BN254. Full replacement of CPU prove with GPU prove can be used with the build tag 'gpu'.
…or NTT and MSM. Add GPU memory cleanup using cudaFree Add GPU version of marshal
Update generation to include build tags
…erations Update iciclegnark dependency to v0.1.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See a few comments.
On a high level I think it is a very good addition to gnark. However, I would restructure the GPU prover a bit. Instead of having the implementation inside backend/groth16/bn254
, I would instead create a new backend backend/groth16/icicle_bn254
and a backend.ProverOption
which would direct to use icicle backend instead of the default one. And in icicle backend I would try to reuse existing structures from CPU backend as much as possible (including marshaling and setup).
Additionally, I would rename the build tag to be icicle
instead of being gpu
- I think it is a bit more descriptive and maybe allows in the future to have similarly other GPU backends unambiguously.
If possible, I would also change the ./setup_icicle.sh
script in the other repo - right now it assumes that $GOPATH
is always ~/go/
, but this may not be the case, you should refer to $GOPATH
explicitly. The setup.sh
script also checks if the user is root or not, but does not fail if the user is not. Additionally, it doesn't really install libbn254.so
, but instead changes $LD_LIBRARY_PATH
temporarily. It is not important in the context of this PR, but I think it would make GPU bindings definitely easier to use. Right now I had to debug the setup scripts to figure out why in other terminal the example was not running.
As a side-note - I ran pairing and scalarmul circuits on Ryzen7 and RTX 3090 machine - the prover was approx 4x faster, but it doesn't take into account the proving key copy from RAM to GPU.
If you would be interested then I could propose some code suggestions about refactoring GPU prover into separate backend.
Suggested edit: diff --git a/go.mod b/go.mod
index 627710bf..8df92783 100644
--- a/go.mod
+++ b/go.mod
@@ -19,11 +19,10 @@ require (
golang.org/x/sync v0.3.0
)
-require github.com/rogpeppe/go-internal v1.11.0 // indirect
-
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 // indirect
+ github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
|
@ivokub Thanks for the review 💪🏻 🚀
Wouldn't this cause there to be a lot of duplicated code between
Updated this 👍🏻
Thanks for the suggestions! This was mainly a quick way to set it up but yes we will make the process more reliable |
Can you have a look at my attempt at branch feat/icicle-integration. It is mostly copy-paste, but on a high level what I did:
Now, for example if I have: proof, err := groth16.Prove(ccs, pk, secretWitness)
if err != nil {
panic(err)
}
// lazy precompute and copy
proofIci, err := groth16.Prove(ccs, pk, secretWitness, backend.WithIcicleAcceleration())
if err != nil {
panic(err)
}
// already precomputed and copied
proofIci2, err := groth16.Prove(ccs, pk, secretWitness, backend.WithIcicleAcceleration())
if err != nil {
panic(err)
}
err = groth16.Verify(proof, vk, publicWitness)
if err != nil {
panic(err)
}
err = groth16.Verify(proofIci, vk, publicWitness)
if err != nil {
panic(err)
}
err = groth16.Verify(proofIci2, vk, publicWitness)
if err != nil {
panic(err)
} Then in case we run it without |
And if this approach looks good then you can merge my |
Looks great 💪🏻 . Love the option to toggle acceleration without rebuilding 🔥 I find it a bit strange to use the I do think it might make adding additional acceleration options difficult but I guess that can be a future problem 😅 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it isn't ideal to have HasIcicle
constant, but I couldn't figure out a nice way to otherwise keep the GPU pointers. One option is to have inside icicle
package a local map from *ProvingKey
to *deviceInfo
, but this affects GC which cannot collect ProvingKey structs anymore nicely. Alternatively, we could amend vanilla (i.e. the structure we embed into icicle.ProvingKey
) bn254.ProvingKey
so that it can have additional backend-specific context. But as you said - I think it is difficult to figure out right now how it should look like and we can try to generalise in the future when we have more backends and intuition how we should store backend-related data.
Otherwise, looks good from my side, but will just ask @gbotrel opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm 👍 amazing work :)
Description
This PR adds experimental support for the Icicle GPU acceleration library using the
gpu
build tag for Groth16 backend and curve BN254.Type of change
How has this been tested?
brevis-cricuits/fabric/bls-sig
run:Checklist:
golangci-lint
does not output errors locally