Skip to content
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

Optimize truth table merge #3993

Merged
merged 3 commits into from
Apr 12, 2024
Merged

Optimize truth table merge #3993

merged 3 commits into from
Apr 12, 2024

Conversation

jackkoenig
Copy link
Contributor

@jackkoenig jackkoenig commented Apr 12, 2024

I'm collecting numbers, but it should be pretty obvious that not essentially doing a deep copy of every TruthTable both before and after running espresso minimization in the common case where the default value is uniform (i.e. all ones, all zeros, or, most commonly, all dont care) will speed things up.

To implement this, I also added some useful methods to BitPat that you can see the tests for.

Doing split and merge on the TruthTable from TruthTableSpec:

  val table = TruthTable(
    Map(
      // BitPat("b000") -> BitPat("b0"),
      BitPat("b001") -> BitPat("b?"),
      BitPat("b010") -> BitPat("b?"),
      // BitPat("b011") -> BitPat("b0"),
      BitPat("b100") -> BitPat("b1"),
      BitPat("b101") -> BitPat("b1"),
      // BitPat("b110") -> BitPat("b0"),
      BitPat("b111") -> BitPat("b1")
    ),
    BitPat("b0")
  )

Before this change:

Benchmark               Mode  Cnt  Score   Error   Units
ChiselBenchmark.Merge  thrpt   10  0.366 ± 0.003  ops/us
ChiselBenchmark.Split  thrpt   10  0.786 ± 0.006  ops/us

After this change:

Benchmark               Mode  Cnt    Score   Error   Units
ChiselBenchmark.Merge  thrpt   10  453.041 ± 1.422  ops/us
ChiselBenchmark.Split  thrpt   10   83.122 ± 0.184  ops/us

Also from a large real design, I measured it was spending 2 minutes in the little filter function in split:

def bpFilter(bitPat: BitPat, indexes: Seq[Int]): BitPat =
(this should use a Set instead of a Seq)
With this change, it now spends 0.3ms in that function which just shows how much unnecessary splitting we were doing 🙃.

Contributor Checklist

  • Did you add Scaladoc to every public function/method?
  • Did you add at least one test demonstrating the PR?
  • Did you delete any extraneous printlns/debugging code?
  • Did you specify the type of improvement?
  • Did you add appropriate documentation in docs/src?
  • Did you request a desired merge strategy?
  • Did you add text to be included in the Release Notes for this change?

Type of Improvement

  • Performance improvement

Desired Merge Strategy

  • Rebase

Release Notes

Reviewer Checklist (only modified by reviewer)

  • Did you add the appropriate labels? (Select the most appropriate one based on the "Type of Improvement")
  • Did you mark the proper milestone (Bug fix: 3.6.x, 5.x, or 6.x depending on impact, API modification or big change: 7.0)?
  • Did you review?
  • Did you check whether all relevant Contributor checkboxes have been checked?
  • Did you do one of the following when ready to merge:
    • Squash: You/ the contributor Enable auto-merge (squash), clean up the commit message, and label with Please Merge.
    • Merge: Ensure that contributor has cleaned up their commit history, then merge with Create a merge commit.

This allows it to test package private methods.
@jackkoenig jackkoenig added Merge with merge commit Please merge with a merge commit, do not squash and merg Performance Improves performance, will be included in release notes labels Apr 12, 2024
@jackkoenig jackkoenig added this to the 6.x milestone Apr 12, 2024
Most TruthTables have a default of all dont care. We can optimize this
common case by doing actual work in TruthTable.split and
TruthTable.merge.
@jackkoenig jackkoenig force-pushed the optimize-truth-table-merge branch from ff87326 to bb32df4 Compare April 12, 2024 00:14
@@ -437,6 +437,18 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, val width: Int)
}
}

/** Are any bits of this BitPat `?` */
private[chisel3] def hasDontCares: Boolean = width > 0 && mask != ((BigInt(1) << width) - 1)
Copy link
Member

Choose a reason for hiding this comment

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

width of bp cannot be 0. Maybe assert out?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm future proofing this such that if we do allow it, these should be correct for it (see stubs in tests).

@jackkoenig
Copy link
Contributor Author

I have added benchmarking results, not extremely rigorous but in practice this is a huge improvement.

@sequencer
Copy link
Member

With this change, it now spends 0.3ms in that function which just shows how much unnecessary splitting we were doing 🙃.

the reason of splitting is because cannot support the existence of both 0, 1 in the result of table. To support this, we have to split it to multiple runs of espresso.

Copy link
Member

@sequencer sequencer left a comment

Choose a reason for hiding this comment

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

LGTM. Let’s make common case fast!
Since split is only designed for long decode output with 0 and 1

@jackkoenig jackkoenig merged commit fcf5770 into main Apr 12, 2024
15 checks passed
@jackkoenig jackkoenig deleted the optimize-truth-table-merge branch April 12, 2024 16:24
@mergify mergify bot added the Backported This PR has been backported label Apr 12, 2024
@mergify mergify bot mentioned this pull request Apr 12, 2024
14 tasks
chiselbot pushed a commit that referenced this pull request Apr 12, 2024
* Move BitPatSpec from package chiselTests to package chisel3

This allows it to test package private methods.

(cherry picked from commit 09d6fa7)

* Add package private all* methods to BitPat

(cherry picked from commit e9a2c6d)

* Optimize TruthTable.split and .merge to do nothing in common case

Most TruthTables have a default of all dont care. We can optimize this
common case by doing actual work in TruthTable.split and
TruthTable.merge.

(cherry picked from commit bb32df4)

---------

Co-authored-by: Jack Koenig <[email protected]>
SpriteOvO pushed a commit that referenced this pull request Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backported This PR has been backported Merge with merge commit Please merge with a merge commit, do not squash and merg Performance Improves performance, will be included in release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants