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

Composite Prime Moduli Sampling and Scaling Factor Calculations (#910 phase 2) #929

Open
wants to merge 25 commits into
base: dev
Choose a base branch
from

Conversation

fdiasmor
Copy link
Collaborator

@fdiasmor fdiasmor commented Jan 3, 2025

No description provided.

@fdiasmor fdiasmor requested a review from yspolyakov January 3, 2025 02:35
@fdiasmor fdiasmor self-assigned this Jan 3, 2025
@fdiasmor fdiasmor linked an issue Jan 3, 2025 that may be closed by this pull request
@fdiasmor fdiasmor changed the base branch from main to dev January 3, 2025 02:35
@fdiasmor fdiasmor changed the title #910 Composite Prime Moduli Sampling and Composite Scaling Factor Calculations Composite Prime Moduli Sampling and Scaling Factor Calculations (#910 phase 2) Jan 10, 2025
src/pke/include/cryptocontext.h Outdated Show resolved Hide resolved
src/pke/include/cryptocontext.h Outdated Show resolved Hide resolved
src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp Outdated Show resolved Hide resolved
src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp Outdated Show resolved Hide resolved
src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp Outdated Show resolved Hide resolved
src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp Outdated Show resolved Hide resolved
src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp Outdated Show resolved Hide resolved
src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp Outdated Show resolved Hide resolved
src/pke/lib/scheme/ckksrns/ckksrns-parametergeneration.cpp Outdated Show resolved Hide resolved
src/pke/lib/schemerns/rns-cryptoparameters.cpp Outdated Show resolved Hide resolved
@@ -2372,11 +2387,19 @@ class CryptoContextImpl : public Serializable {
void ModReduceInPlace(Ciphertext<Element>& ciphertext) const {
ValidateCiphertext(ciphertext);

GetScheme()->ModReduceInPlace(ciphertext, BASE_NUM_LEVELS_TO_DROP);
if (isCKKS(m_schemeId)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Any CKKS-specific code should be implemented inside the folder for the CKKS scheme (not in global cryptocontext code)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

Ciphertext<Element> ciphertext = EvalMult(ciphertext1, ciphertext2);
algo->KeySwitchInPlace(ciphertext, evalKey);
ModReduceInPlace(ciphertext, BASE_NUM_LEVELS_TO_DROP);
uint32_t levelsToDrop = BASE_NUM_LEVELS_TO_DROP;
if (cc->getSchemeId() == CKKSRNS_SCHEME) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this code here rather then in CKKS files?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

@@ -66,6 +66,7 @@
#include <algorithm>
#include <unordered_map>
#include <set>
#include <iostream>
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is not what i meant. I would consider the code for DEBUG_KEY as legacy, and we prefer not to expand it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should I remove all the code under DEBUG_KEY? I only added the header because of pre-commit complaints. Let me know.

* GetCompositeDegree: get composite degree of the current scheme crypto context.
* @return integer value corresponding to composite degree
*/
uint32_t GetCompositeDegreeFromCtxt() const {
Copy link
Collaborator

Choose a reason for hiding this comment

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

GetCompositeDegreeFromCtxt() should be in either protected or private section of CryptoContextImpl as it is used only inside the class

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed it.

std::cout << __FUNCTION__ << "::" << __LINE__ << " numPrimes: " << numPrimes << " qBound: " << qBound
<< std::endl;
}
numPrimes *= compositeDegree;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just a question: this multiplication numPrimes *= compositeDegree; used to be performed for scalTech == COMPOSITESCALINGAUTO || scalTech == COMPOSITESCALINGMANUAL only. Now it is done for any scalTech. Is this correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since it is a CKKS class, yes, because on single scaling mode it will be multiplied by 1. So, I figured we don't really need the overhead of branch prediction.

const auto cryptoParams = std::dynamic_pointer_cast<CryptoParametersRNS>(ciphertextVec[0]->GetCryptoParameters());
uint32_t levelsToDrop = cryptoParams->GetCompositeDegree();

for (size_t i = 0; i < lim; i = i + 2) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

this for loop should be split: the logic to calculate ciphertextVec's index is complicated as there are 2 additional conditions to check in every iteration. a possible solution could look like this (we can discuss the changes):

    size_t ctrIndex = 0;
    size_t i = 0;
    for (; i < (inSize - 1); i += 2) {
        ciphertextMultVec[ctrIndex] = algo->EvalMultAndRelinearize(ciphertextVec[i], ciphertextVec[i + 1], evalKeys);
        algo->ModReduceInPlace(ciphertextMultVec[ctrIndex++], levelsToDrop);
    }
    if(i < inSize) {
        ciphertextMultVec[ctrIndex] = algo->EvalMultAndRelinearize(ciphertextVec[i], ciphertextVec[0], evalKeys);
        algo->ModReduceInPlace(ciphertextMultVec[ctrIndex++], levelsToDrop);
        i += 2;
    }
    for (; i < lim; i += 2) {
        ciphertextMultVec[ctrIndex] =
            algo->EvalMultAndRelinearize(ciphertextMultVec[i - inSize], ciphertextMultVec[i + 1 - inSize], evalKeys);
        algo->ModReduceInPlace(ciphertextMultVec[ctrIndex++], levelsToDrop);
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That works except that the second operand inside the special case is ciphertextMultVec[i + 1 - inSize].

size_t ctrIndex = 0;

auto algo = ciphertextVec[0]->GetCryptoContext()->GetScheme();
const auto cc = ciphertextVec[0]->GetCryptoContext();
Copy link
Collaborator

Choose a reason for hiding this comment

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

cc is not used here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought I had removed that... Thanks for picking up. Compiler should have complained. Fixed it now.

@@ -46,6 +46,32 @@ CKKS implementation. See https://eprint.iacr.org/2020/1118 for details.

namespace lbcrypto {

Ciphertext<DCRTPoly> AdvancedSHECKKSRNS::EvalMultMany(const std::vector<Ciphertext<DCRTPoly>>& ciphertextVec,
const std::vector<EvalKey<DCRTPoly>>& evalKeys) const {
if (ciphertextVec.size() < 1)
Copy link
Collaborator

@dsuponitskiy dsuponitskiy Feb 5, 2025

Choose a reason for hiding this comment

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

if ciphertextVec.size() == 1 then the loop below is not executed. possibly if (ciphertextVec.size() < 2) would suffice? Also, return ciphertextMultVec.back(); will cause a segfault if ciphertextVec.size() == 1

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This implementation is borrowed from the base-advancedshe.cpp. This fix will be propagated to the original implementation in base-advancedshe.cpp as follows:

if (ciphertextVec.size() < 2)
        OPENFHE_THROW("Input ciphertext vector size should be 1 or more");
    
if (ciphertextVec.size() == 1) return ciphertextVec[0];

uint32_t levelsToDrop = BASE_NUM_LEVELS_TO_DROP;
if (cryptoParams->GetScalingTechnique() == COMPOSITESCALINGAUTO ||
cryptoParams->GetScalingTechnique() == COMPOSITESCALINGMANUAL) {
const auto cryptoRNSParams = std::dynamic_pointer_cast<CryptoParametersRNS>(cryptoParams);
Copy link
Collaborator

Choose a reason for hiding this comment

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

cryptoRNSParams is not needed, you could re-use cryptoParams

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure what happened here. Also just above, the line const auto cc = ciphertext1->GetCryptoContext(); is not needed either.

@fdiasmor fdiasmor requested a review from dsuponitskiy February 6, 2025 01:33
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.

Add CKKS Composite Scaling
3 participants