-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Low memory prover #2670
Low memory prover #2670
Conversation
Nice! I'm going to review the PR later this week, but one initial comment: please rebase this PR to edit the first commit to restore its original commit message (use |
4d2246d
to
66d08c3
Compare
Done. |
The commit message "Delete libsnark tests that we've merged into gtest." does not match the contents of that commit. |
66d08c3
to
87703d3
Compare
My mistake. Should be fine now. Though rebase still makes me a little uncomfortable so would be happy if someone verified. |
const size_t chunks = omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or call omp_set_num_threads() | ||
#else | ||
const size_t chunks = 1; | ||
#endif |
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.
Suggestion for another PR: refactor this to const size_t chunks = MULTICORE_CHUNKS();
and move the preprocessor conditional to a header.
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.
Whitespace
@@ -439,10 +513,6 @@ r1cs_ppzksnark_proof<ppT> r1cs_ppzksnark_prover(const r1cs_ppzksnark_proving_key | |||
{ | |||
enter_block("Call to r1cs_ppzksnark_prover"); | |||
|
|||
#ifdef DEBUG | |||
assert(constraint_system.is_satisfied(primary_input, auxiliary_input)); | |||
#endif |
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.
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.
Is there some git trick to add this to the commit where it was deleted? Or should I make a new commit?
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.
git rebase -i <COMMIT_ID_BEFORE_THIS>
- Select this commit to be edited (change
pick
toe
) - Edit the file to add this back in (copy from this diff, and remove the leading
-
s) - Add this change
git commit --amend
git diff HEAD^..HEAD
and check this part of the diff is no longer there.git rebase --continue
to finish.
Alternatively:
- Make a new commit that exactly reverses this one change.
git rebase -i <COMMIT_ID_BEFORE_THIS>
- Move the new commit line underneath this commit's line, and change it from
pick
tos
(squash)
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.
Great explanation!
assert(pk.C_query.domain_size() == qap_wit.num_variables()+2); | ||
assert(pk.H_query.size() == qap_wit.degree()+1); | ||
assert(pk.K_query.size() == qap_wit.num_variables()+4); | ||
#endif |
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.
These debug assertions have been dropped. Is this intentional?
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.
@ebfull ?
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.
They could be left in.
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.
I think this can't be left in cause it needs all the proving key at once.
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.
Most of this could be split across the various functions. The for loop would be harder though, and given that we don't set DEBUG
, I'm fine with leaving these out.
const Fr<ppT> t = Fr<ppT>::random_element(); | ||
qap_instance_evaluation<Fr<ppT> > qap_inst = r1cs_to_qap_instance_map_with_evaluation(constraint_system, t); | ||
assert(qap_inst.is_satisfied(qap_wit)); | ||
#endif |
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.
Is dropping this debug assertion intentional?
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.
@ebfull ?
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.
It was intentional when we did it. I can't remember the reason why though. It could be left in -- after all, we don't enable DEBUG
anyway.
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.
added back
src/zcash/JoinSplit.cpp
Outdated
|
||
return ZCProof(r1cs_ppzksnark_prover<ppzksnark_ppT>( | ||
pk, | ||
// TODO |
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.
What is to do here?
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.
@ebfull ?
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.
I can't remember, it should be removed.
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.
removed
src/zcash/JoinSplit.cpp
Outdated
pk, | ||
// TODO | ||
if(!fh.is_open()) { | ||
throw std::runtime_error((boost::format("could not load param file at %s") % pkPath).str()); |
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.
We don't use boost::format
, we use tinyformat.
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 #2243 (comment)
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.
fixed
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.
also second instance
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.
Concept ACK and preliminary utACK. I've checked that the refactor appears to be a no-op. Daira's comments need addressing.
87703d3
to
3a0034b
Compare
const Fr<ppT> t = Fr<ppT>::random_element(); | ||
qap_instance_evaluation<Fr<ppT> > qap_inst = r1cs_to_qap_instance_map_with_evaluation(constraint_system, t); | ||
assert(qap_inst.is_satisfied(qap_wit)); | ||
#endif |
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.
It was intentional when we did it. I can't remember the reason why though. It could be left in -- after all, we don't enable DEBUG
anyway.
assert(pk.C_query.domain_size() == qap_wit.num_variables()+2); | ||
assert(pk.H_query.size() == qap_wit.degree()+1); | ||
assert(pk.K_query.size() == qap_wit.num_variables()+4); | ||
#endif |
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.
They could be left in.
The math is good, the code and logic is good, I like the API changes, nice and clean. Just might as well put those DEBUG assertions back even if we're not enabling them ever. (I consider that kind of pre-processor-macro-debug-assertion to be an anti-pattern though, since it doesn't expand templates and create static assertions and things like that.) |
3a0034b
to
8eeda60
Compare
There might be a memory leak. Tops out with virtual memory at 9GB and actual usage spiking to 7GB.
The above was conducted with zcash in regtest mode. |
@bitcartel I wonder if it's related to this comment 929b9db#r120993316 If I understand what @daira said there, it's not a problem? |
Btw, wouldn't you get a similar thing with the regular joinsplit before these changes? I remember memory not going down at the end of a joinsplit when checking with htop |
corrected link to Daira's comment #2243 (comment) |
@arielgabizon This depends on the libc implementation (did the allocator use the heap pool or dedicated pages? if it's the heap pool, how fragmented is it?). This is non-deterministic platform-specific voodoo, and I would not be surprised if "often" the memory remains reserved as far as the OS can see. To be sure it's really freed up, we'd have to take over and do the |
@tromer I don't know this stuff, and not sure how you do it yourself; would be happy to fix it if someone explained it to me. @daira said here #2679 that it currently allocates on the stack and we should change that. Though she also said in the comment I linked above that it can wait for a future PR. |
Ohh you perhaps were talking about the joinsplit before this code change. |
Yes. @daira is right that it should be on the heap, and that's all that matters for the current PR. An additional issue, which should not be addressed in the current PR, is that even when using the heap (whether it's the old prover or the new prover), the memory may remain reserved unless you use a special allocator. Fixing that would probably be platform-specific and a bit tricky. |
@bitcartel you might want to try this version I wrote. https://github.com/arielgabizon/zcash/tree/lowmemmovetoheap |
@arielg I tried the other branch, same results with zcbenchmark createjoinsplit. Anyway, I don't think this is a blocker, given that this issue already exists and has been documented. |
Well glad it's not a blocker. I see more memory released in the other branch when using |
💔 Test failed - pr-merge |
One of the Boost tests is failing. The error message:
|
Ugh, address looks like an offset from NULL. |
Reproducible. |
Looks like that test fails only with the last commit that puts the ifstream object on the head, which increases running time by 0.5 seconds according to @str4d , maybe just abort that commit for now? |
⌛ Trying commit 4305a56 with merge 94e19023bc8ca82661ae015c3b898dd6b5fbde48... |
Still seeing that failure:
|
💔 Test failed - pr-try |
BasicTestingSetup::BasicTestingSetup() | ||
{ | ||
assert(init_and_check_sodium() != -1); | ||
ECC_Start(); | ||
pzcashParams = ZCJoinSplit::Unopened(); |
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.
This is the cause of the crash. Previously TestingSetup
had access to pzcashParams
because it inherits from BasicTestingSetup
. With this change, it doesn't have that defined any more, leading to a null pointer error in rpc_wallet_tests
(which uses TestingSetup
). I think the best solution is to have TestingSetup
inherit from JoinSplitTestingSetup
.
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.
Oh, and if we do this, the test that was triggering this bug then fails:
test/rpc_wallet_tests.cpp(1377): error: in "rpc_wallet_tests/rpc_z_shieldcoinbase_internals": check string(e.what()).find("JoinSplit verifying key not loaded")!= string::npos has failed
@@ -154,10 +110,6 @@ class JoinSplitCircuit : public JoinSplit<NumInputs, NumOutputs> { | |||
uint64_t vpub_new, | |||
const uint256& rt | |||
) { | |||
if (!vk || !vk_precomp) { | |||
throw std::runtime_error("JoinSplit verifying key not loaded"); |
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.
I'm going to just alter the test to check for the error we actually get now, given that this error has been removed.
@zkbot try |
Low memory prover This PR integrates @ebfull 's low memory changes: https://github.com/zcash/zcash/pull/2243/commits on top of @str4d 's work bringing in libsnark as a subtree 4699d0e
☀️ Test successful - pr-try |
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.
ACK bef1b5c
@zkbot r+ |
📌 Commit bef1b5c has been approved by |
Low memory prover This PR integrates @ebfull 's low memory changes: https://github.com/zcash/zcash/pull/2243/commits on top of @str4d 's work bringing in libsnark as a subtree 4699d0e
Thanks for merging! I will be able to run actual release soon :) |
Interestingly, the memory peak now and previously, is not during proof generation but during creating the joinsplit gadget https://github.com/zcash/zcash/blob/master/src/zcash/JoinSplit.cpp#L276. |
This PR integrates @ebfull 's low memory changes: https://github.com/zcash/zcash/pull/2243/commits
on top of @str4d 's work bringing in libsnark as a subtree
4699d0e