-
Notifications
You must be signed in to change notification settings - Fork 101
[Draft] Scheme selection passes #2043
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
base: main
Are you sure you want to change the base?
Conversation
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 agree with Alex that this would need to run at a high enough level where we haven't yet run approximation / arithmetization.
At those high levels I expect we'll also see linalg operations / matmul operations that would be arithmetic operations (and heavily weighted to arithmetic schemes)
| bool initialized; | ||
| int numBoolOps; | ||
| int numBitOps; | ||
| int numIntArithOps; |
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.
in a scheme selection, i would think that if arith ops have smaller bit width (2-8 bits), the cost of evaluation in CGGI like schemes will be lower than high bit width arithmetic (8+ bits). i think this info doesn't synthesize this but maybe the cost model can take this into consideration?
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 that's a great point, since arithmetic width should be pretty essential to any reasonable cost model!
|
I think the core question here is really what the cost model needs to look like. I think the current bool/bit/arith ops counter approach is too simplistic to be useful, yet at the same time I don't think we need some super complex model based on lots of benchmarks/etc. I think the hardest part is to find some way to track roughly what kind of mult-depth/bootstrapping obligation a program induces (when viewed as an arithmetic problem). Accounting for the cost of basic arithmetic (considering bitwidth, as mentioned by Asra) should be relatively straightfoward, especially if we make some simplifying assumptions on roughly how expensive a matmul/etc will be (which does depend on the kernel, but I don't think the cost model needs to be all that accurate). Since really, the main question for HEIR right now is "do we do binarization or do we do arithmetization", we can probably just track two accountings of the costs, one assuming we went for CGGI and one assuming we went for CKKS/BGV/BFV and ignore the finer points inside those approaches until HEIR actually supports, e.g, circuit bootstrapped CGGI or interpolation-based airhtmetization for BFV/BGV. Btw, I don't think its very important for the cost model to be "correct" at the moment, it just needs to be reasonable, i.e., don't pick CGGI for a program with 12 64-bit matmuls just because it sees one comparison at the end, or pick CKKS with N=64k and 1000-bit modulus for a program that only operates on like 4 small inputs in total, just because it's all add/mul ops. |
|
@kragall I see the "PR format requirements" failed - you should follow the steps at https://heir.dev/docs/development/ and run |
|
Sorry, forgot about |
8e5d307 to
7b02a3e
Compare
|
The current SchemeInfoAnalysis annotates the You can run both analysis by using |
There must be some unpushed changes because heir-opt doesn't build on your branch. It's missing a BUILD file in |
|
Adding the build file and otherwise it seems to work for me: $ bazel run //tools:heir-opt -- --annotate-scheme-info --debug --debug-only=SchemeInfo $PWD/tests/Examples/common/dot_product_8.mlir
Visiting: arith.constant. Visiting: arith.constant. Visiting: tensor.extract. Visiting: tensor.extract. Visiting: arith.muli. Counting: NatureOfComputation(numBoolOps=0; numBitOps=0; numIntArithOps=1; numRealArithOps=0; numCmpOps=0; numNonLinOps=0)
Visiting: arith.addi. Counting: NatureOfComputation(numBoolOps=0; numBitOps=0; numIntArithOps=1; numRealArithOps=0; numCmpOps=0; numNonLinOps=0)
Visiting: arith.addi. Counting: NatureOfComputation(numBoolOps=0; numBitOps=0; numIntArithOps=1; numRealArithOps=0; numCmpOps=0; numNonLinOps=0)
Counting here: arith.constant
Counting here: arith.constant
Counting here: affine.for
Counting here: tensor.extract
Counting here: tensor.extract
Counting here: arith.muli
Counting here: arith.addi
Counting here: affine.yield
Counting here: func.return
Writing annotations here: func.func
module {
func.func @dot_product(%arg0: tensor<8xi16> {secret.secret}, %arg1: tensor<8xi16> {secret.secret}) -> i16 attributes {natcomp.bitOps = 0 : i64, natcomp.boolOps = 0 : i64, natcomp.cmpOps = 0 : i64, natcomp.intOps = 3 : i64, natcomp.nonLinOps = 0 : i64, natcomp.realOps = 0 : i64} {
%c0 = arith.constant 0 : index
%c0_i16 = arith.constant 0 : i16
%0 = affine.for %arg2 = 0 to 8 iter_args(%arg3 = %c0_i16) -> (i16) {
%extracted = tensor.extract %arg0[%arg2] : tensor<8xi16>
%extracted_0 = tensor.extract %arg1[%arg2] : tensor<8xi16>
%1 = arith.muli %extracted, %extracted_0 {natcomp.intOps = 1 : i64} : i16
%2 = arith.addi %arg3, %1 {natcomp.intOps = 1 : i64} : i16
affine.yield %2 : i16
}
return %0 : i16
}
} |
|
Perhaps one thing to note is that the analysis won't "visit" your |
|
So |
|
I'm not sure I understand the problem. The function is annotated in the example above. What outcome are you trying to achieve? |
|
After annotating |
|
Ah yes, you won't be able to do it in an analysis using the data flow framework. But you could just do the analysis work in the pass after the analysis is run, as you said with a walk. You can also just create any sort of class object you want and call it from inside runOnOperation. |
This is a draft of how scheme selection could be handled with HEIR on a very abstract level. The idea is that this could be helpful to non-expert users and could be a stepping stone towards dealing with scheme switching, see the discussion in #2019.