Microsoft SEAL中CKKS的向量点积

3
目前我正在尝试使用Microsoft SEAL库实现矩阵乘法方法。我已经创建了一个作为输入矩阵的vector<vector<double>>,并使用CKKSEncoder对其进行编码。然而,编码器将整个向量打包成单个Plaintext,因此我只有一个vector<Plaintext>,这使我失去了二维结构(然后当然在加密后我将有一个vector<Ciphertext>)。拥有一个一维向量允许我完全访问行,但无法访问列。
我设法在编码之前转置矩阵。这样,我就可以逐个乘积地乘以第一个矩阵的行和第二个矩阵的列(在转置形式中的行),但我无法将结果向量的元素相加,因为它被打包成单个Ciphertext。我只需要弄清楚如何在SEAL中使向量点积工作以执行矩阵乘法。我是不是漏掉了什么或者我的方法有问题?
2个回答

2
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);

1
谢谢。我想我在Github上看到了你的逻辑回归项目。做得很好。 - sleepyhead

-1

向量的向量与数组的数组(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()。但是,您不能声明vector(W) of vector(H)。
附言:有很多C++实现的数学向量和矩阵。如果您不想处理C风格的数组,可以使用其中之一。

这并不是我的问题。我只是在问是否可以使用Microsoft SEAL进行向量点积。我知道向量和数组之间有区别,但如果我想创建一个二维数组,那么我就必须对其中的每个元素进行编码,这在计算上是非常昂贵的。我正在尝试对整个向量进行编码以从SIMD中获益。 - Marwan N

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接