带有 CKKS 的 Microsoft 密封中的矢量点积
Vector dot product in Microsoft SEAL with CKKS
我目前正在尝试使用 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 样式数组,则可以使用其中之一。