Benchmarking GPU Acceleration for ZK-Snarks
ProtoLayers Talks · June 2024 · 18:36
Mohamed Amine Kthiri of Maya-ZK presents benchmarking results for GPU acceleration of ZK-SNARKs, using the open-source libraries gnark and icicle. The talk covers both the performance gains and the economics of running GPUs for proof generation, weighing speed against the cost of hardware for zero-knowledge systems.
Speakers
Topics
From ProtoLayers Talks, hosted by ProtoLayers.
Transcript
okay so um as I said I will be presenting uh a work I did a couple months ago about benchmarking ZK snarks GPU acceleration um in this work we used the um um uh the the library gnark with in in tandem with icycle um so how do I move arrow down arrow down okay okay good or to the right it's not working try uh okay right okay good so um a bit of an agenda so I will first be I will be first introducing the work like why are we doing this why does it matter then I will be talking a bit about how
we benchmarked what we're trying to Benchmark and then finally we'll get to geek out about some numbers and eventually try to come up with some meaningful conclusions from it so starting with the introduction why are we doing this so the main idea here is that zero knowledge proofs are very expensive and slow therefore gpus are uh are basically used to make them faster now the question is is it really worth it like is it worth it to deploy GPU like from a cost perspective for energy and hardware and also what kind of gpus do I need is is a GPU from a couple of generations old um good enough or do I need like the latest and greatest so um basically when we tried
to answer these questions we couldn't find really good good answers available so the problem is that ZK snarks use a lot of Primitives like msms and entities and while the hardware acceleration of these Primitives have been like an open field of study the problem is that most benchmarks do not Benchmark the effect on the ZK snark as a whole but only on these Primitives so what we want to do in this work is to answer the question of how does GPU acceleration affect the performance of a full ZK snark um we also wanted to to use um open- Source uh software for this um for this work so we we decided to use gnark in
tandem with icle so gnark is basically the library we use to write the ZK snarks while icle is the implementation of the GPU acceleration if you look at the image here you can see how icle is basically built so icle is just um uh is just the um these um Primitives that are written in C and it provides bindings for go L and rust and given that gnark is built is written in go then it was we were able to use icicle for it and now moving on to the benchmarking setup um as we mentioned we wanted to to see whether we could use old or new hardware so we built two test benches
for this purpose one is a high-end test bench within uh with an RT with Nvidia RTX a5000 while the other one is a lowend test bench where we had multiple I would say old gpus like GTX 1060 1070 Quadro m2000 like we basically wanted to know like how low can we [Music] go for the ZK Nar configuration we uh we chose the G 16 as a back end this is not a choice we made we that was the only um implemented uh algorithm on the Gnar um on the gnark library for CPU acceleration um for the circuit we wanted something that is a bit more practical so we chose a shot 256 circuit
where we have two inputs the pre-image and the hash and we basically want want to prove that we know the the pre-image of a already existing hash um another thing about ZK KN is that there is a lot of um elliptic curve arithmetic involved so when using e case narc you need to to instantiate it on a certain curve um we went with three curves the BN 254 the bls2 377 and the BW 6761 and now a quick look at how we decided to uh our on our benchmarking strategy so the first thing we do is that we basically um uh choose the pre-image size we had three sizes 32
bytes 1 kiloby and 32 kilobytes this effectively changes the size of of the circuit so that we can so that we can see the effect of GP acceleration on circuits of different sizes then we choose the elliptic curve and randomly generate 100 pairs of hashes and pre-images and eventually after running the algorithm with and without GPU acceleration we calculate the average runtime but we also keep track of some of the GPU stats like the memory the utilization and the power so overall we have 18 benchmarks in total now enough uh with that let's move on to to the um to the numbers and the results um starting with a bit of a
spoiler sadly we won't be featuring any results from the lowend test bench for a number of reasons one some of the gpus failed all of the benchmarks due to limited vram two even the gpus that managed some Benchmark none of them managed all of the benchmarks also due to vram limitations and last and and and last but not least the for the successful benchmarks we had worse performance with GPU acceleration than without which is I know very weird and we Tred to investigate the reason but we could not because it was out of the scope of the work um um but yeah I mean I mean know seriously
um we tried Benchmark I mean I I tried looking into it but it was um maybe a bit out of my uh technical reach but um I would say I would blame it on icycle because it's it's still experimental it was still still experimental when I used it but I uh they had like a couple of the new versions like since uh since last time I used it so oh I would hope it would be much better now um starting with the most obvious um with the most obvious um metric which is the runtime and as you can see here dep uh depending on the pre-image size the larger the pre-image the larger the circuit and and consequently the the
higher the runtime um we can also see that the um the GPU acceleration did give us some significant speed UPS um I know it's not really um clear in the first two pre-image sizes but it is there if you look close enough um the other thing is is that um we also noticed that uh the choice of the curve uh really changes like um uh it changes the runtime so the larger the curve elements so the curve the size of the curve element is basically the last three numbers uh in the name of each curve the um the more time it takes to run uh to run the ZK snark whether that is with or without GPU
acceleration um next we look at the circuit size so um circuit size is measured in number of constraints so every circuit will eventually be um be transformed into a system of um rank one constraints and um as you can see here um it's it's not really um linear uh it's it's not really uh proportional so going from 32 bytes to 1 kiloby we get like a 4X uh 4X um more constraints and then going from 1 kilobyte to 32 kilobytes we get around a 22x um first uh so um we're going to Benchmark the different um uh the different steps of the Z snark starting with the circuit compilation and setup
um as you can see for the circuit compilation which is the transformation of the of the circuit from a program to like a system of constraints um the choice of curve did not really have much of an effect and most and the worst one was like around um uh 80 Seconds however for the setup it is a different story so uh if you take closely you see that the setup is actually in minutes not in seconds so especially for the 32 KOB PR image size with the bw6 Curve it took almost 3 hours luckily in a practical in a practical scenario this does not matter because these steps need to be only ran once so in Practical scenario even if I accelerate this like um a lot
it wouldn't matter because they would only be run once and not once each new uh pair of inputs um then we also wanted to see like which steps of the ZK nark uh take the most amount of front time um as you can clearly see here the witness generation and and proof verification are nowhere to be seen so the other two steps which are the solution generation and the proof generation take around um 99% of the um runtime therefore we'll be taking a closer look on these those two steps um the second thing that we wanted to look at mainly was the GPU acceleration speed up um on the left we have the acceleration the speed up for
the full zase narc and while on the right hand we have the proof generation speed up for or only the um the proof Generation Um as you can notice with larger circuits we have we have a smaller and smaller um uh speed up and we also notice that the speed up is always much better for the for the bw6 curve and uh again that will be a common Trend in this Benchmark it's basically because um the larger the the curve elements the more computationally intensive it is and the the better it utilizes um the GPU um next we want to look a bit on to the GPU stats uh more closely um here we look at the average memory average and
Peak memory consumption and um as you can see here um while for the first two pre-image sizes it was not as large it kind of shoots up when we go to 32 kilobytes and reaches an EST standing up to 27 GB of vram which really only a few cards at least in the consumer or P prosumer markets have um the other the other point I wanted to mention is that we looked at the memory Evolution across across like different truns and what's what's interesting here is that um the um the GPU memory kind of always shoots up and then comes back to a certain Baseline um
which means that the ZK snark itself does not use all of the ram reported but only a certain portion of it um this like around 1,000 megab of ram here in this example is pre-allocated to some uh to some uh keys that are needed for computation um this is important if you want to batch because it means that we can in fact put more um put more ZK snarks to uh instances to run in parallel together the second stat we want to look at is the utilization and here we kind of have a sort of a um weird um weird setup where the average utilization kind of goes down with the pre-image size but the peak utilization goes up um this is
clearly indicative of the fact that that the um GPU is not utilized throughout the whole uh ZK snark and it's mostly running in bursts but at very high utilization rate um the last metric we look at is the power consumption and uh again this is um more or less similar to the utilization which which makes sense because both are correlated but it is a little less pronounced here because um as you can see the average power consumption itself goes down with the pre-image size but the peak power consumption also goes up which is further indication of like these um births that I was talking about um to confirm this um to confirm this
hypothesis we took a look at the uh Evolution over three runs for the GPU power and utilization and um what we notice is that although they are strongly cor correlated they're not really um the same so um if you look at the first two graphs you'll see that although the um the utilization goes up and down the power remains more or less constant this is basically um this is basically a hardware limitation where the power consumption cannot jump down directly to zero so if it's fast enough then the power consumption does not have time to go back to zero although although the utilization goes down to zero um however if we look at the third curve which is um much larger in time you can
see that uh that when the utilization drops down to zero the power drops down but not quite to idle levels so we have like some um some substantial power loss there and then it eventually goes down to like these ID levels and then it goes back up again um so these curves basically show that we have a very inefficient um Power use here of the GPU not only in terms of usage but also in term of uh utilization but also in terms of power looking at the power itself is not enough uh we also wanted to look at this from a financial point of view and basically we looked we calculated the energy consumption now if you look at this curve you'll see that it's very
different than that of the utilization and the main reason for that is is basically the runtime so Al although we have like very similar um Power utilization uh average the run times are are very uh are very different from each other so that's why the 32 kiloby has like a very large um energy consumption when compared to the other two um again back to the economy thing to put this more in money um in money terms we calculated the cost of GPU acceleration for 1 million ZK Narron assuming an electricity price of 20 cents and uh here are the results we came up with and as you can see for especially for the large Circuit of 32 kilobytes these uh these costs come can
be um very expensive um now um enough with the numbers um let's try to to come up with something meaningful from them and basically we have four main takeaways the first takeaway is that the circuit is important so the size of the circuit is crucial to to the decision of whether we should employ GPU acceleration or not and we clear clearly see in the numbers here that large circuits are more inefficient when using GPU and also provide less speed up here we Define large circuits at circuits with more than 10 million constraints the second takeaway is that curves are also important so um
depending on what curves you want to use um it would be it it would be probably more or less beneficial to um uh to invest in in GPU acceleration and um like just um heads up just that large curves are more resource intensive so um so um so the other thing is that the curve Choice also affects the GPU choice so some some curves use so much RAM that you can't even use some specific um GPU models um the third takeaway goes hand in hand with the previous statements which is that vram is critical because we saw um we saw peaks of up to 27 GB which means that other gpus are
practically not usable for um GPU acceleration um this could be changed if for example we have multi multi GPU support but um as far as I know that's still not implemented in in icle um the other point that I want to mention is that not all the memory is used by the ZK snark so batching multiple runs is possible of course with enough vram so just because one run consumes 10 gigabytes does not mean that two runs will consume 20 and the last the last takeaway is that more utilization equals more efficiency I know seems kind of obvious but the idea here is that GPU powers and utilization while they are correlated
they are not the same this means that using the GPU imur as we as we saw in the time evolution is inefficient compared to continuous use therefore a good solution for this would be would be to batch all of the DK Primitives together for multiple runs and run them continuously um as uh as everything is life nothing is perfect and we had a few limitations of course there was the small range of tested gpus it will and and also we did not account for CPU energy when we were when we were making our uh energy calculations so we were kind of unfair to the GPU acceleration side and made it look more expensive than what it is um we also did not do any overclocking
that's for future work I guess and the last thing was that proof just generated with the GPU acceleration were not valid this was also out of the scope of this work I tried investigating it but it I could not really come up with a very good answer um and last note I want to touch on which is the developer experience um one one of the goals of this work was to also see like the uh the options there are for uh for open source solutions for Z ZK snark GPU accelerations and they were very far and few in between um actually this was the only setup I would say that we kind of got to work and it was not really uh trivial so my opinion there's still a
lot of more work to do to get like to something that is a deployment ready and I also think that there's a lot of place for um optimization as clearly mentioned um thank you everyone um the full write up is available on our blog if you're interested in more numbers and everything and the code is also available if you want to run it on yourself and test your own gpus um thank you everyone that was it and happy to take any questions