-1

To all he-experts out there:

I want to implement a matrix-vector multiplication with very large matrices (600000 x 55). Currently I am able to perform he operations like Addition, Multiplication, InnerProduct etc. with small inputs. When I try to apply these operations on larger inputs I get errors like Invalid next size (normal) or I ran out of main memory until the os kills the process (exit code 9).

Do you have any recommendations/examples how to archive an efficient way of implementing a matrix-vector multiplication or something similar? (Using BFV and CKKS).

PS: I am using the PALISADE library but if you have better suggestions like SEAL or Helib I would happily use them as well.

IanQ
  • 1,831
  • 5
  • 20
  • 29
Cowas
  • 328
  • 2
  • 12
  • 3
    Please don't vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right, under the [CC BY-SA 4.0 license](https://creativecommons.org/licenses/by-sa/4.0/), for Stack Exchange to distribute that content (i.e. regardless of your future choices). By Stack Exchange policy, the non-vandalized version of the post is the one which is distributed, and thus, any vandalism will be reverted. If you want to know more about deleting a post please see: [How does deleting work?](/help/what-to-do-instead-of-deleting-question). – cigien Jul 14 '21 at 12:54

1 Answers1

3

CKKS, which is also available in PALISADE, would be a much better option for your scenario as it supports approximate (floating-point-like) arithmetic and does not require high precision (large plaintext modulus). BFV performs all operations exactly (mod plaintext modulus). You would have to use a really large plaintext modulus to make sure your result does not wrap around the plaintext modulus. This gets much worse as you increase the depth, e.g., two chained multiplications.

For matrix-vector multiplication, you could use the techniques described in https://eprint.iacr.org/2019/223, https://eprint.iacr.org/2018/254, and the supplemental information of https://eprint.iacr.org/2020/563. The main idea is to choose the right encoding and take advantage of SIMD packing. You would work with a power-of-two vector size and could pack the matrix either as 64xY (multiple rows) per ciphertext or a part of each row per ciphertext, depending on which one is more efficient.

  • Thank you for your answer! I tried implementing a matrix vector multiplication with the CKKS scheme(same parameter setting like in the ..pke/advanced-real-number.cpp. If I apply a EvalMult() operation a vector of the size(~600000) I can create a packed plaintext and do the multiplication on the ciphertext but the result is only as long as the half number of depth which cant be bigger than 2^16. Which I dont really understand. ? – Cowas Aug 05 '20 at 14:45
  • Secondly I tried your suggested approach where I pack a partial pieces of my input matrix execute the multiplication on them seperatly and aggregate them back together. But every solution I implemented takes quite a long time(>15min) to execute which feels like that I am doing something wrong. Could you please elaborate a little bit more your suggested approach (like what parameters to choose etc.) Thank you in advance! – Cowas Aug 05 '20 at 14:50
  • 2
    For the first question, we can pack up to n/2 real numbers into one CKKS ciphertext, where n is the ring dimension. This is a limitation of CKKS packing itself. I would like to note that depth and batch size (number of slots) are two different concepts. `depth` is how many chained multiplications one can perform, `number of plaintext slots` is how many real numbers one can pack in a single ciphertext to perform operations in a SIMD manner. – Yuriy Polyakov Aug 06 '20 at 15:38
  • 2
    For the question on performance, the first suggestion is to make sure you set multDepth to 1 to work with smaller parameters. The second suggestion is related to encoding. You want to make sure you place n/2 real numbers into one ciphertext so you use the least number of ciphertexts. Then you have a couple of options how you can write the matrix in vectors of size n/2. For instance, you can use row-wise or column-wise ordering. The high-level idea is that EvalSum for adding real numbers within the same ciphertext is much more expensive than EvalAdd over multiple ciphertexts. – Yuriy Polyakov Aug 06 '20 at 15:40
  • Thanks for all the help! Maybe you could look at this post as well: https://stackoverflow.com/questions/63464518/apply-homomorphic-operations-on-large-encrypted-data – Cowas Aug 18 '20 at 08:17