-
Notifications
You must be signed in to change notification settings - Fork 274
CBMC additional profiling info: Extend solver hardness to track clauses mapped to an instruction #5480
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
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #5480 +/- ##
===========================================
+ Coverage 69.33% 69.35% +0.01%
===========================================
Files 1242 1242
Lines 100417 100433 +16
===========================================
+ Hits 69622 69653 +31
+ Misses 30795 30780 -15
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
src/solvers/solver_hardness.cpp
Outdated
@@ -91,10 +93,20 @@ void solver_hardnesst::register_clause(const bvt &bv) | |||
{ | |||
current_hardness.clauses++; | |||
current_hardness.literals += bv.size(); | |||
std::vector<int> clause; |
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.
int
? or do we want a type with a defined length like int_64
?
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 are the memory and performance implications of storing a copy of the clauses?
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 haven't explored this yet. Although a much more efficient approach would be to store some form of index (specifically an index interval) to some existing clause storage, but I am not sure if this can be done.
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 are the metrics that you want to compute based on the clauses?
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.
To identify which program lines contribute to the SAT core. So given this infrastructure we can map clauses from the SAT core directly to LOC.
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 are tools which compute the UNSAT core given a CNF formula and DRAT proof of unsatisfiability (these proofs have become a standard in the SAT competitions). CBMC is used to get the dimacs CNF formula (--dimacs) and the clause to LOC mapping with --write-solver-stats-to option.
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.
If this can only be used wiith dimacs couldn't you just store the index (eg. line of the clause) in the dimacs output?
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.
How do I access the dimacs clause index here? Also is the dimacs output ordered?
I will need to map lines of program code to indices in the dimacs output.
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.
You can make dimacs_cnft
(or probably cnf_clause_listt
) implement hardness_collectort
(in the same way other sat solvers implement that interface). It seems that the clauses are stored in order in cnf_clause_listt
, so dimacs_cnft
will print them in the same order as you get the register_clause
calls. Of course, you'll have to test and confirm that.
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 now keep track of the clause counter in satcheck_minisat2_baset<T>::lcnf
that calls register_clause
and store the counter value rather than the clause itself in solver hardness. Have added optional DEBUG statements to verify if these match corresponding lines in the dimacs output.
src/solvers/solver_hardness.cpp
Outdated
} | ||
clause.push_back(0); | ||
std::sort(clause.begin(), clause.end()); |
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.
Do we want to sort before or after we add the 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.
Post processing of the SAT core cnf runs sort for the entire clause, including the zero. So might as well sort it here too.
src/solvers/solver_hardness.cpp
Outdated
|
||
int signed_literal = literal.var_no(); | ||
if(literal.sign()) | ||
signed_literal = -signed_literal; |
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.
Any chance this could overflow?
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 what is used inside CBMC already for the literal.dimacs() function. I'm assuming here that they have already taken into consideration any potential overflow issues. And also, they define the return type as int.
src/solvers/solver_hardness.cpp
Outdated
{ | ||
json_arrayt clause_json; | ||
for(auto const &lit : clause) | ||
clause_json.push_back(json_numbert{std::to_string(lit)}); |
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.
json_numbert
takes a string?
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.
Yes, takes a string but the output is formatted json number.
@@ -26,6 +26,8 @@ operator+=(const solver_hardnesst::sat_hardnesst &other) | |||
clauses += other.clauses; | |||
literals += other.literals; | |||
variables.insert(other.variables.begin(), other.variables.end()); | |||
clause_set.insert( |
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.
Should we sort this?
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 was worried about too many calls to sort().
src/solvers/solver_hardness.cpp
Outdated
@@ -91,10 +93,20 @@ void solver_hardnesst::register_clause(const bvt &bv) | |||
{ | |||
current_hardness.clauses++; | |||
current_hardness.literals += bv.size(); | |||
std::vector<int> clause; |
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.
Should we typedef this?
with_solver_hardness([&bv, &solver_clause_num](solver_hardnesst &hardness) { | ||
hardness.register_clause(bv, solver_clause_num); |
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.
Pass the clause counter to hardness.register_clause(). Store the clause counter value rather than the clause themselves.
src/solvers/solver_hardness.cpp
Outdated
#ifdef DEBUG | ||
std::cout << solver_clause_num << ": "; | ||
for(const auto &literal : bv) | ||
std::cout << literal.dimacs() << " "; | ||
std::cout << "0\n"; | ||
#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.
Debug statements to output 'clause_counter_value: clause' to cross check if they match the corresponding lines in dimacs output.
@@ -140,8 +140,10 @@ void satcheck_minisat2_baset<T>::lcnf(const bvt &bv) | |||
|
|||
solver->addClause_(c); | |||
|
|||
with_solver_hardness( | |||
[&bv](solver_hardnesst &hardness) { hardness.register_clause(bv); }); | |||
size_t solver_clause_num = clause_counter; |
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.
Assignment seems redundant, just use clause_counter
in line 145.
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.
clause_counter
is an inherited data member of satcheck_minisat2_baset<T>
from cnf_solvert
so I cannot pass it directly to the lambda capture list (not in scope). Will need to pass this
instead. Thought it would be better to just pass a copy.
src/solvers/solver_hardness.h
Outdated
@@ -50,6 +50,7 @@ struct solver_hardnesst | |||
size_t clauses = 0; | |||
size_t literals = 0; | |||
std::unordered_set<size_t> variables = {}; | |||
std::vector<int> clause_set = {}; |
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.
std::vector<int> clause_set = {}; | |
std::vector<size_t> clause_set = {}; |
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.
Done.
src/solvers/solver_hardness.cpp
Outdated
std::cout << "0\n"; | ||
#endif | ||
|
||
current_hardness.clause_set.push_back(solver_clause_num + 1); |
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.
Please add a comment to explain why +1.
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.
Done.
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 have done quite a bit of performance optimisation work on CBMC. If you want a chat about it then drop me a line.
@@ -140,8 +140,22 @@ void satcheck_minisat2_baset<T>::lcnf(const bvt &bv) | |||
|
|||
solver->addClause_(c); | |||
|
|||
// To map clauses to lines of program code, track clause indices in the |
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 don't want to be a downer on this but ...
-
There is not necessarily a 1-to-1 correlations between clauses and lines of code. For example, rewriting and normalisation may mean that multiple lines reduce to the same shared term. Which line should this be credited to? This is worse when it is things like multiplication where additions from other operations can appear as sub-parts of the operator.
-
Number of variables and clauses is a very crude measure of SAT difficulty. Reducing the number of clauses can make the problem harder; I have seen multiple instances of this.
void register_clause(const bvt &bv); | ||
/// \param cnf: processed clause | ||
/// \param cnf_clause_index: index of clause in dimacs output | ||
/// \param register_cnf: negation of boolean variable tracking if the clause |
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.
Please clarify this comment.
@@ -50,6 +50,7 @@ struct solver_hardnesst | |||
size_t clauses = 0; | |||
size_t literals = 0; | |||
std::unordered_set<size_t> variables = {}; | |||
std::vector<size_t> clause_set = {}; |
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 the performance cost of this?
…just number of clauses Currently, solver hardness tracks number of clauses and not the actual clauses for an instruction. This mapping will help identfy code hotspots based on which of the clauses belong to the SAT core. This commit extends the sat_hardnesst structure to include mapping between clauses and ssa expression.
…put for write-solver-stats-to Clauses are stored as a sorted vector of integers.
…put for write-solver-stats-to Clauses are stored as a sorted vector of integers. clang format solver_hardness.cpp
…he clause itself Add comment to explain solver_clause_num + 1 in solver hardness, change <int> to <size_t>
…he clause itself Add comment to explain solver_clause_num + 1 in solver hardness, change <int> to <size_t> Remove sorting of clause set keeping performance in mind
…he clause itself Add comment to explain solver_clause_num + 1 in solver hardness, change <int> to <size_t> Remove sorting of clause set keeping performance in mind Add additional utility to map program lines to clauses in --dimacs output clang format
11000b3
to
d9e87db
Compare
…he clause itself Add comment to explain solver_clause_num + 1 in solver hardness, change <int> to <size_t> Remove sorting of clause set keeping performance in mind Add additional utility to map program lines to clauses in --dimacs output clang format
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-cmake-gcc GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-macos-10_15-make-clang GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-cmake-gcc GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-cmake-gcc GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. Also fix the status tracking in do_prop_solve as the previous implementation would keep the solver in an UNSAT state, even when assumptions had been modified. This issue was surfaced by the cbmc-incr-oneloop suite of regression tests. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the Glucose interface to match these changes. To avoid future regressions, make the check-macos-10_15-cmake-clang GitHub action use Glucose.
In diffblue#5480 the solver hardness interface was updated, but changes were only implemented in the Minisat2 interface. Update the IPASIR interface to match these changes. Also fix the status tracking in do_prop_solve as the previous implementation would keep the solver in an UNSAT state, even when assumptions had been modified. This issue was surfaced by the cbmc-incr-oneloop suite of regression tests. To avoid future regressions, make the check-ubuntu-20_04-make-gcc GitHub action use IPASIR with Riss as the back-end solver.
Currently solver hardness tracks number of clauses. This is an extension of solver hardness to track the clauses themselves. Provides a mapping between clauses and instructions.