-
Notifications
You must be signed in to change notification settings - Fork 107
Lowering for comparisons in arithmetic pipeline #1999
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
5f2e348 to
521c0a9
Compare
|
Ok, so after re-enabling OpenMP support for OpenFHE and allowing the python frontend to actually use OpenFHE in multi-threaded mode, it was at least somewhat more feasible to try and run the generated program. Unfortunately, it'll eventually fail with an OpenFHE Error (see below). Nevertheless, I think this is a good point to start getting some reviews and try and to get this PR merged, since it's already doing a lot of things, and I assume the fix for whatever noise/scale/etc management thing is going wrong here will be its own issue and PR.
EDIT: I think I'll actually pull the OpenMP thing out of this PR, as it seems like the least related and easiest to extract + I want to make sure it works on a variety of machines before we merge it and accidentally break the OpenFHE backend |
521c0a9 to
508bfc5
Compare
eb5ee8a to
784bd67
Compare
lib/Transforms/PolynomialApproximation/PolynomialApproximation.cpp
Outdated
Show resolved
Hide resolved
784bd67 to
e18096f
Compare
|
Also note I'm working on upstreaming the sign ops in j2kun/llvm-project#8 |
23ad395 to
d4eb60d
Compare
|
I've just noticed that there's another open issue regarding lowering of arith.cmpi #827. Would there be a benefit to having this as an alternative approach to the |
Right, now that we have a LattiGo backend, the interpolation based approaches might indeed be viable! I'd say it's a lower priority right now but I'd be happy to offer my assistance if someone wants to try :) |
|
The comparisons have been bugging me for a while now. I'll have a look, but I can't commit much time for them right now. Why does the LattiGo backend make that approach more viable? Meanwhile, I managed to crash the |
This commit enables the existing polynomial approximation for the default arithmetization pipeline, adds a lowering from arith.cmpi/cmpf to an arithmetic expression using sign(x), which is then lowered using the polynomial approximation framework. Note that this currently only supports a < b and a > b comparions, but not ==,<= or >= (since equality requires a different strategy rather than "just" sign(x)). Also, the lowering currently only makes sense for CKKS, as the sign(x)-based approach requires a (scalar/plaintext) division by half / multiplication with 0.5. Towards the goal of enabling arith.cmpi/cmpf, specifically those arising from non-data-oblivious high-level code, this commit includes a variety of "enablement" changes/fixes: * Improves `--convert-secret-for-to-static-for` pass This now handles various edge cases correctly, such as dynamic (but not secret) lower/upper bounds, scf.for bounds that are signless integers rather than index type, and correctly refuses to translate an scf.for with dynamic step value (which scf.for allows but affine.for does not). The pass now also by default converts all scf.for (even non-secret ones) to affine.for, as the rest of the piepline cannot handle nested scf.for even if the inner loop is not secret-dependent. This can be toggled off using the `convert-all-scf-for` flag on the pass (default = true). * `--add-client-interface` now also works for multiple functions Specifically, it adjusts the insertion point logic so that __encrypt/etc helpers are emitted directly after the function in question. Apparently, this is already enough to avoid the pass trying to process one of the helper functions it added itself, though it is unclear whether this is a stable/guaranteed behavior. * Adds support for `IndexType` in `ConvertToCiphertextSemantics` * In Layout assignment, assigns layout for index type operands of arith.cmpi * Creates a new `math_ext` dialect and adds `math_ext.sign` op * Adds the lowerings for arith.cmpi/cmpf -> math.sign * Adds polynomial-approximation passes to the arithmetization Pipelines
d4eb60d to
15757ce
Compare
For this, you need the plaintext modulus
Thanks, good catch! I wasn't taking into account different float types when creating the |
asraa
left a 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.
Thanks for adding the follow-up TODOs!
| The behavior is undefined for NaN inputs. | ||
| }]; | ||
| let arguments = (ins SignlessIntegerOrFloatLike:$value); | ||
| let results = (outs SignlessIntegerOrFloatLike:$result); |
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 the result just be SignlessIntegerLike? I would expect that the result shouldn't be a float
edit: after finishing my review i realize it's floatlike too because the result types probably need to be float for CKKS
This is work towards fixing #1929 (for loop with secret bound) which primarily hinges on the ability to actually lower a comparison to a polynomial approximation.
So far, this (draft) PR has been work to get to the point where we can rewrite the code from #1929 all the way down to just having
math_ext.signthat needs to be arithmetized/lowered to a polynomial.On the way there, I ended up touching a bunch of places, though:
--convert-secret-to-static-forto make it more robust/handle more edge cases--add-client-interfacecapable of handling multiplefunc.funcin the same module(purely to avoid needing to split into multiple teot files, not directly related to the comparison issue)
IndexTypeto the type conversions in--convert-to-ciphertext-semantics(this will appear to "fix" Unexpected segfault after compilation error in
--convert-to-ciphertext-semantics#1992 but really that issue isn't about the inability to lowerarith.index_castbut about the compiler segfaulting after encountering an op it cannot lower)--layout-propagation:The pass previously assumed that index type'd operands don't need to have a layout assigned (i.e., index valued scalars don't need to be converted to ciphertext-sized tensors) which is true for most index type values (e.g., the offset in a rotation, the indices in a tensor.extract/insert, etc). However, in the case of index values appearing in an
arith.cmpi, we do need to assign them a layout (and they do need to be turned into ciphertext-sized vectors) because we will be doing math to them as part of the lowering. There was already a comment to suggest defining an op interface that can be used to decide whether a given op operand needs to have a layout assigned, and I think this would indeed be the correct solution. My current ugly hack simply hard-codes an exception forarith.cmpiinto the index type skipping code.math_extdialect with a single opmath_ext.sign, with plans to move this upstream tomath--comparison-to-sign-rewritethat rewritesarith.cmpi/arith.cmpf:Currently, the pass only supports a < b or b > a, no equality. It also assumes that you can multiply with 0.5, so really only makes sense in a CKKS pipeline, though I've currently just added it to
--mlir-to-secret-arithmetic. For BGV/BFV, comparison usually involves approximatingmod trather thansign....The next step would be to try and actually enable polynomial approximation for
math_ext.signand see if the resulting programs to anything useful :)EDIT: This now works for the full
--mlir-to-ckkspipeline 🎉 but of course I had to make a few more changes along the way:--polynomial-approximationto the arithmetic pipeline and addedmath_ext.signloweringlwe.reinterpret_application_data, as with other conversion) forarith.sitofp/uitofp/fptosi/tptoui(int/float conversions) to--secret-to-ckks--lower-polynomial-evalto the arithmetic pipeline and had to make a few changes there:I had to change the degreeThreshold interpretation to be "inclusive" (I guess, alternatively, I could have bumped up the max from 5 to 6?) because the previous pass would generate degree 5 polynomials and the threshold was 5 here.
I also had to add a
convertFloatToSemanticsfunction (mostly AI generated, and 100% AI named 😉) to make sure the pass would generate Attributes compatible withf32values if that's what the original program was using, as float attributes apparently get interpreted asf64if parsed from text?scf.if->arith.select-> mul/add/etc rewrites would introduce ani1type which OpenFHE would realize asstd::vector<int64_t>but MakePackedCKKSPlaintext only accepts double, so we emit one more vector copy/conversion in this case.Final task: run the generated openfhe code and see if it does anything even remotely related to the original program 😅
EDIT2: If you rebase this on top of the mlir_src python frontend branch, you can run the example/test directly from python 🎉 ....but it'll be horrendously slow since I guess it'll run OpenFHE single threaded? Also, the example includes several bootstrap calls, so it'll be slow no matter what...