带有 CKKS 的 Microsoft 密封中的矢量点积

Vector dot product in Microsoft SEAL with CKKS

本文关键字:密封 CKKS Microsoft 带有      更新时间:2023-10-16

我目前正在尝试使用 Microsoft SEAL 库实现矩阵乘法方法。我创建了一个vector<vector<double>>作为输入矩阵,并用CKKSEncoder对其进行编码。但是,编码器将整个矢量打包成一个Plaintext所以我只有一个vector<Plaintext>,这使我丢失了2D结构(然后当然,加密后我会有一个vector<Ciphertext>(。拥有 1D 向量允许我只能完全访问行,而不能访问列。

我设法在编码之前转置矩阵。这允许我将第一个矩阵的行和第二个矩阵的列(转置形式的行(按分量相乘,但我无法将结果向量的元素相加,因为它被打包到一个密文中。我只需要弄清楚如何使矢量点积在 SEAL 中工作以执行矩阵乘法。我错过了什么还是我的方法错了?

KyoohyungHan在问题中提出了:https://github.com/microsoft/SEAL/issues/138 可以通过旋转输出向量并反复求和来解决旋转问题。

例如:

// my_output_vector is the Ciphertext output
vector<Ciphertext> rotations_output(my_output_vector.size());
for(int steps = 0; steps < my_output_vector.size(); steps++)
{
evaluator.rotate_vector(my_output_vector, steps, galois_keys, rotations_output[steps]);
}
Ciphertext sum_output;
evaluator.add_many(rotations_output, sum_output);

向量的向量与数组数组(2D,矩阵(不同。

虽然一维vector<double>.data()指向连续的内存空间(例如,您可以对此执行memcpy(,但每个"子向量"分配自己的独立内存缓冲区。因此vector<vector<double>>.data()没有意义,不能用作矩阵。

在C++中,二维数组array2D[W][H]存储在内存中与array[W*H]相同。因此,两者都可以通过相同的例程处理(当它有意义时(。请考虑以下示例:

void fill_array(double *array, size_t size, double value) {
for (size_t i = 0; i < size; ++i) {
array[i] = value;
}
}
int main(int argc, char *argv[])
{
constexpr size_t W = 10;
constexpr size_t H = 5;
double matrix[W][H];
// using 2D array as 1D to fill all elements with 5.
fill_array(&matrix[0][0], W * H, 5);
for (const auto &row: matrix) {
for (const auto v : row) {
cout << v << 't';
}
cout << 'n';
}
return 0;
}

在上面的示例中,您可以将double matrix[W][H];替换为vector<double> matrix(W * H);并将matrix.data()馈送到fill_array()中。但是,不能声明向量 (H( 的向量 (W(。

附言数学向量和矩阵有很多C++实现。如果您不想处理 C 样式数组,则可以使用其中之一。