Skip to content

Strash index was always calculated at 0, leading to 100% collisions#17

Closed
ecordell wants to merge 2 commits intogo-air:masterfrom
ecordell:strash-index-fix
Closed

Strash index was always calculated at 0, leading to 100% collisions#17
ecordell wants to merge 2 commits intogo-air:masterfrom
ecordell:strash-index-fix

Conversation

@ecordell
Copy link
Copy Markdown

@ecordell ecordell commented Aug 24, 2021

This is how the structural hash in gini is computed:

gini/logic/c.go

Line 379 in a1a5030

return uint32((a << 13) * b)

But when it’s used, it’s used “mod capacity” of the nodes - which are always multiples of 2. The index into the strash array is always a*2^13*b % 2^n which is 0 for n<13:

gini/logic/c.go

Lines 268 to 271 in a1a5030

c := strashCode(a, b)
l := uint32(cap(p.nodes))
i := c % l
si := p.strash[i]

gini/logic/c.go

Lines 285 to 287 in a1a5030

k := c % uint32(cap(p.nodes))
m.n = p.strash[k]
p.strash[k] = j

and leads to 100% collisions on the table - it will always try to store in index 0 and have to walk back through the node links.

To fix this, I changed the index calculation to strash % (cap - 1)

I added a small benchmark that uses the existing sudoku example as a sanity check:

// before
BenchmarkSudoku-12    	     894	   1752632 ns/op
// after
BenchmarkSudoku-12    	     741	   1467374 ns/op

which is a ~15% speedup.

(I'm sure there are much better ways to check this; it seems like the bench command would work)

It's also entirely possible I'm not understanding what is supposed to be happening, please enlighten me if that's the case!


This change is Reviewable

@scott-cotton
Copy link
Copy Markdown
Member

scott-cotton commented Aug 24, 2021

Eric, thanks much for your PR. Indeed the hash was colliding. However, the sudoku test isn't really affected, nor is any solving inside this project (or it would have been noticed earlier).

logic.C is used for creating formulas before sending them to the solver. Since the solving time dominates on interesting problems, this went unnoticed.

But, a small variation on your change:

--- a/logic/c.go
+++ b/logic/c.go
@@ -376,5 +376,5 @@ func (p *C) grow() {
 }

 func strashCode(a, b z.Lit) uint32 {
-       return uint32((a << 13) * b)
+       return uint32(^(a << 13) * b)
 }

gives a huge speedup on constructing logic formulas.

I added this bench:

+type cAdder struct {
+       c   *logic.C
+       f   z.Lit
+       buf []z.Lit
+}
+
+func (a *cAdder) Add(m z.Lit) {
+       if m != z.LitNull {
+               a.buf = append(a.buf, m)
+               return
+       }
+       clause := a.c.F
+       for _, m := range a.buf {
+               clause = a.c.Or(clause, m)
+       }
+       a.buf = a.buf[:0]
+       a.f = a.c.And(a.f, clause)
+}
+
+func BenchmarkStrash(b *testing.B) {
+
+       for i := 0; i < b.N; i++ {
+               circuit := logic.NewC()
+               ca := &cAdder{
+                       c: circuit,
+                       f: circuit.T}
+               gen.Rand3Cnf(ca, 100, 300)
+       }
+}

to test for it and got this:

scott@pavillion gini % go test -bench=. ./logic # with change
BenchmarkStrash-8   	   42534	     27721 ns/op
PASS
ok  	github.com/go-air/gini/logic	2.130s

scott@pavillion gini % go test -bench=. ./logic # without change

BenchmarkStrash-8   	    1322	    899904 ns/op
PASS
ok  	github.com/go-air/gini/logic	1.762s

Would you like to submit something along these lines?

@scott-cotton
Copy link
Copy Markdown
Member

(I think this will help https://github.com/go-air/reach a lot)

Copy link
Copy Markdown
Member

@scott-cotton scott-cotton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon reflection, the lits are 32bit so overflow happens a lot on bigger problems, and where there is overflow the hash is distributed. But a huge improvement for the smaller problems.

Reviewable status: 0 of 2 files reviewed, all discussions resolved

Copy link
Copy Markdown
Member

@scott-cotton scott-cotton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 2 files reviewed, 2 unresolved discussions (waiting on @ecordell)


sudoku_test.go, line 13 at r1 (raw file):

Quoted 5 lines of code…

	for i := 0; i < b.N; i++ {
		Example_sudoku()
	}
}

Please see alternate test in the discussion


logic/c.go, line 379 at r1 (raw file):

func strashCode(a, b z.Lit) uint32 {
	return uint32((a << 13) * b)

I think
return uint32(^(a<<13) * b)
is preferable because the change is in one place, preserving the idea of the strashCode, and it uses all the capacity.

Copy link
Copy Markdown
Member

@scott-cotton scott-cotton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well not quite "overflow", but more evenly distributed for larger problems.

Reviewable status: 0 of 2 files reviewed, 2 unresolved discussions (waiting on @ecordell)

scott-cotton added a commit that referenced this pull request Aug 25, 2021
Thanks to Evan Cordell who spotted a problem with the strash code colliding.
Interesting, as it has a strong impact on the logic/c performance
(but none on solving).

See #17
@scott-cotton
Copy link
Copy Markdown
Member

Evan, Thanks a lot for the PR.

In the interest of time, I went ahead and submitted the alternative in the review and cut a new release. (contributor agreement and not sure of your level of interest).

Please feel free to follow up in any way.

@ecordell
Copy link
Copy Markdown
Author

Thanks @scott-cotton! Your reasoning makes sense

ecordell added a commit to ecordell/operator-lifecycle-manager that referenced this pull request Aug 26, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18
ecordell added a commit to ecordell/operator-lifecycle-manager that referenced this pull request Aug 26, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18
ecordell added a commit to ecordell/operator-lifecycle-manager that referenced this pull request Aug 26, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
openshift-merge-robot pushed a commit to operator-framework/operator-lifecycle-manager that referenced this pull request Aug 26, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
ankitathomas pushed a commit to ankitathomas/operator-framework-olm that referenced this pull request Sep 8, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
ankitathomas pushed a commit to ankitathomas/operator-framework-olm that referenced this pull request Sep 9, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
timflannagan pushed a commit to timflannagan/operator-framework-olm that referenced this pull request Sep 28, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
timflannagan pushed a commit to timflannagan/operator-framework-olm that referenced this pull request Sep 28, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
timflannagan pushed a commit to timflannagan/operator-framework-olm that referenced this pull request Sep 29, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
timflannagan pushed a commit to timflannagan/operator-framework-olm that referenced this pull request Sep 29, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
timflannagan pushed a commit to timflannagan/operator-framework-olm that referenced this pull request Oct 13, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
njhale pushed a commit to njhale/operator-framework-olm that referenced this pull request Oct 13, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
timflannagan pushed a commit to njhale/operator-framework-olm that referenced this pull request Nov 15, 2021
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
perdasilva pushed a commit to perdasilva/operator-framework-olm that referenced this pull request Mar 4, 2022
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
perdasilva pushed a commit to perdasilva/operator-framework-olm that referenced this pull request Mar 4, 2022
new version has logic.C performance improvements that should help

see:
- go-air/gini#17
- go-air/gini@3a1a4d9
- go-air/gini@8dd6805
- go-air/gini#18

Signed-off-by: Evan <cordell.evan@gmail.com>
Upstream-repository: operator-lifecycle-manager
Upstream-commit: c20784d3e2a372c2a6a03dbcfedf512ca84b1eca
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 this pull request may close these issues.

2 participants