Browse Source

Preprocessing and storage of incremental RDPFs

Ian Goldberg 1 year ago
parent
commit
89ecb9f81f
7 changed files with 157 additions and 51 deletions
  1. 55 25
      mpcio.cpp
  2. 20 0
      mpcio.hpp
  3. 28 4
      mpcio.tcc
  4. 23 13
      preproc.cpp
  5. 3 0
      rdpf.hpp
  6. 24 9
      rdpf.tcc
  7. 4 0
      types.hpp

+ 55 - 25
mpcio.cpp

@@ -234,12 +234,12 @@ void MPCIO::dump_stats(std::ostream &os)
 // TVA is a tuple of vectors of arrays of PreCompStorage
 template <nbits_t WIDTH, typename TVA>
 static void rdpfstorage_init(TVA &storage, unsigned player,
-    ProcessingMode mode, unsigned num_threads)
+    ProcessingMode mode, unsigned num_threads, bool incremental)
 {
     auto &VA = std::get<WIDTH-1>(storage);
     VA.resize(num_threads);
-    char prefix[11];
-    strcpy(prefix, "rdpf");
+    char prefix[12];
+    strcpy(prefix, incremental ? "irdpf" : "rdpf");
     if (WIDTH > 1) {
         sprintf(prefix+strlen(prefix), "%d_", WIDTH);
     }
@@ -253,13 +253,13 @@ static void rdpfstorage_init(TVA &storage, unsigned player,
 // TVA is a tuple of vectors of arrays of PreCompStorage
 template <nbits_t WIDTH, typename TVA>
 static void rdpfstorage_dumpstats(std::ostream &os, TVA &storage,
-    size_t thread_num)
+    size_t thread_num, bool incremental)
 {
     auto &VA = std::get<WIDTH-1>(storage);
     for (nbits_t depth=1; depth<=ADDRESS_MAX_BITS; ++depth) {
         size_t cnt = VA[thread_num][depth-1].get_stats();
         if (cnt > 0) {
-            os << " r" << int(depth);
+            os << (incremental ? " i" : " r") << int(depth);
             if (WIDTH > 1) {
                 os << "." << int(WIDTH);
             }
@@ -296,11 +296,16 @@ MPCPeerIO::MPCPeerIO(unsigned player, ProcessingMode mode,
     for (unsigned i=0; i<num_threads; ++i) {
         valselecttriples.emplace_back(player, mode, "selects", i);
     }
-    rdpfstorage_init<1>(rdpftriples, player, mode, num_threads);
-    rdpfstorage_init<2>(rdpftriples, player, mode, num_threads);
-    rdpfstorage_init<3>(rdpftriples, player, mode, num_threads);
-    rdpfstorage_init<4>(rdpftriples, player, mode, num_threads);
-    rdpfstorage_init<5>(rdpftriples, player, mode, num_threads);
+    rdpfstorage_init<1>(rdpftriples, player, mode, num_threads, false);
+    rdpfstorage_init<2>(rdpftriples, player, mode, num_threads, false);
+    rdpfstorage_init<3>(rdpftriples, player, mode, num_threads, false);
+    rdpfstorage_init<4>(rdpftriples, player, mode, num_threads, false);
+    rdpfstorage_init<5>(rdpftriples, player, mode, num_threads, false);
+    rdpfstorage_init<1>(irdpftriples, player, mode, num_threads, true);
+    rdpfstorage_init<2>(irdpftriples, player, mode, num_threads, true);
+    rdpfstorage_init<3>(irdpftriples, player, mode, num_threads, true);
+    rdpfstorage_init<4>(irdpftriples, player, mode, num_threads, true);
+    rdpfstorage_init<5>(irdpftriples, player, mode, num_threads, true);
     for (unsigned i=0; i<num_threads; ++i) {
         cdpfs.emplace_back(player, mode, "cdpf", i);
     }
@@ -336,11 +341,16 @@ void MPCPeerIO::dump_precomp_stats(std::ostream &os)
         if (cnt > 0) {
             os << " s:" << cnt;
         }
-        rdpfstorage_dumpstats<1>(os, rdpftriples, i);
-        rdpfstorage_dumpstats<2>(os, rdpftriples, i);
-        rdpfstorage_dumpstats<3>(os, rdpftriples, i);
-        rdpfstorage_dumpstats<4>(os, rdpftriples, i);
-        rdpfstorage_dumpstats<5>(os, rdpftriples, i);
+        rdpfstorage_dumpstats<1>(os, rdpftriples, i, false);
+        rdpfstorage_dumpstats<2>(os, rdpftriples, i, false);
+        rdpfstorage_dumpstats<3>(os, rdpftriples, i, false);
+        rdpfstorage_dumpstats<4>(os, rdpftriples, i, false);
+        rdpfstorage_dumpstats<5>(os, rdpftriples, i, false);
+        rdpfstorage_dumpstats<1>(os, irdpftriples, i, true);
+        rdpfstorage_dumpstats<2>(os, irdpftriples, i, true);
+        rdpfstorage_dumpstats<3>(os, irdpftriples, i, true);
+        rdpfstorage_dumpstats<4>(os, irdpftriples, i, true);
+        rdpfstorage_dumpstats<5>(os, irdpftriples, i, true);
         cnt = cdpfs[i].get_stats();
         if (cnt > 0) {
             os << " c:" << cnt;
@@ -361,6 +371,11 @@ void MPCPeerIO::reset_precomp_stats()
         rdpfstorage_resetstats<3>(rdpftriples, i);
         rdpfstorage_resetstats<4>(rdpftriples, i);
         rdpfstorage_resetstats<5>(rdpftriples, i);
+        rdpfstorage_resetstats<1>(irdpftriples, i);
+        rdpfstorage_resetstats<2>(irdpftriples, i);
+        rdpfstorage_resetstats<3>(irdpftriples, i);
+        rdpfstorage_resetstats<4>(irdpftriples, i);
+        rdpfstorage_resetstats<5>(irdpftriples, i);
     }
 }
 
@@ -376,11 +391,16 @@ MPCServerIO::MPCServerIO(ProcessingMode mode,
         std::deque<tcp::socket> &p1socks) :
     MPCIO(2, mode, p0socks.size())
 {
-    rdpfstorage_init<1>(rdpfpairs, player, mode, num_threads);
-    rdpfstorage_init<2>(rdpfpairs, player, mode, num_threads);
-    rdpfstorage_init<3>(rdpfpairs, player, mode, num_threads);
-    rdpfstorage_init<4>(rdpfpairs, player, mode, num_threads);
-    rdpfstorage_init<5>(rdpfpairs, player, mode, num_threads);
+    rdpfstorage_init<1>(rdpfpairs, player, mode, num_threads, false);
+    rdpfstorage_init<2>(rdpfpairs, player, mode, num_threads, false);
+    rdpfstorage_init<3>(rdpfpairs, player, mode, num_threads, false);
+    rdpfstorage_init<4>(rdpfpairs, player, mode, num_threads, false);
+    rdpfstorage_init<5>(rdpfpairs, player, mode, num_threads, false);
+    rdpfstorage_init<1>(irdpfpairs, player, mode, num_threads, true);
+    rdpfstorage_init<2>(irdpfpairs, player, mode, num_threads, true);
+    rdpfstorage_init<3>(irdpfpairs, player, mode, num_threads, true);
+    rdpfstorage_init<4>(irdpfpairs, player, mode, num_threads, true);
+    rdpfstorage_init<5>(irdpfpairs, player, mode, num_threads, true);
     for (unsigned i=0; i<num_threads; ++i) {
         p0ios.emplace_back(std::move(p0socks[i]), "p0", i);
     }
@@ -396,11 +416,16 @@ void MPCServerIO::dump_precomp_stats(std::ostream &os)
             os << " ";
         }
         os << "T" << i;
-        rdpfstorage_dumpstats<1>(os, rdpfpairs, i);
-        rdpfstorage_dumpstats<2>(os, rdpfpairs, i);
-        rdpfstorage_dumpstats<3>(os, rdpfpairs, i);
-        rdpfstorage_dumpstats<4>(os, rdpfpairs, i);
-        rdpfstorage_dumpstats<5>(os, rdpfpairs, i);
+        rdpfstorage_dumpstats<1>(os, rdpfpairs, i, false);
+        rdpfstorage_dumpstats<2>(os, rdpfpairs, i, false);
+        rdpfstorage_dumpstats<3>(os, rdpfpairs, i, false);
+        rdpfstorage_dumpstats<4>(os, rdpfpairs, i, false);
+        rdpfstorage_dumpstats<5>(os, rdpfpairs, i, false);
+        rdpfstorage_dumpstats<1>(os, irdpfpairs, i, true);
+        rdpfstorage_dumpstats<2>(os, irdpfpairs, i, true);
+        rdpfstorage_dumpstats<3>(os, irdpfpairs, i, true);
+        rdpfstorage_dumpstats<4>(os, irdpfpairs, i, true);
+        rdpfstorage_dumpstats<5>(os, irdpfpairs, i, true);
     }
     os << "\n";
 }
@@ -413,6 +438,11 @@ void MPCServerIO::reset_precomp_stats()
         rdpfstorage_resetstats<3>(rdpfpairs, i);
         rdpfstorage_resetstats<4>(rdpfpairs, i);
         rdpfstorage_resetstats<5>(rdpfpairs, i);
+        rdpfstorage_resetstats<1>(irdpfpairs, i);
+        rdpfstorage_resetstats<2>(irdpfpairs, i);
+        rdpfstorage_resetstats<3>(irdpfpairs, i);
+        rdpfstorage_resetstats<4>(irdpfpairs, i);
+        rdpfstorage_resetstats<5>(irdpfpairs, i);
     }
 }
 

+ 20 - 0
mpcio.hpp

@@ -223,12 +223,22 @@ struct MPCPeerIO : public MPCIO {
     using RDPFPrecomps =
         std::vector<std::array<
             PreCompStorage<RDPFTriple<WIDTH>, RDPFTripleName>,ADDRESS_MAX_BITS>>;
+    template <nbits_t WIDTH>
+    using IRDPFPrecomps =
+        std::vector<std::array<
+            PreCompStorage<RDPFTriple<WIDTH>, IRDPFTripleName>,ADDRESS_MAX_BITS>>;
     std::tuple<
         RDPFPrecomps<1>,
         RDPFPrecomps<2>,
         RDPFPrecomps<3>,
         RDPFPrecomps<4>,
         RDPFPrecomps<5>> rdpftriples;
+    std::tuple<
+        IRDPFPrecomps<1>,
+        IRDPFPrecomps<2>,
+        IRDPFPrecomps<3>,
+        IRDPFPrecomps<4>,
+        IRDPFPrecomps<5>> irdpftriples;
 
     MPCPeerIO(unsigned player, ProcessingMode mode,
             std::deque<tcp::socket> &peersocks,
@@ -255,12 +265,22 @@ struct MPCServerIO : public MPCIO {
     using RDPFPrecomps =
         std::vector<std::array<
             PreCompStorage<RDPFPair<WIDTH>, RDPFPairName>,ADDRESS_MAX_BITS>>;
+    template <nbits_t WIDTH>
+    using IRDPFPrecomps =
+        std::vector<std::array<
+            PreCompStorage<RDPFPair<WIDTH>, IRDPFPairName>,ADDRESS_MAX_BITS>>;
     std::tuple<
         RDPFPrecomps<1>,
         RDPFPrecomps<2>,
         RDPFPrecomps<3>,
         RDPFPrecomps<4>,
         RDPFPrecomps<5>> rdpfpairs;
+    std::tuple<
+        IRDPFPrecomps<1>,
+        IRDPFPrecomps<2>,
+        IRDPFPrecomps<3>,
+        IRDPFPrecomps<4>,
+        IRDPFPrecomps<5>> irdpfpairs;
 
     MPCServerIO(ProcessingMode mode,
             std::deque<tcp::socket> &p0socks,

+ 28 - 4
mpcio.tcc

@@ -62,13 +62,25 @@ RDPFTriple<WIDTH> MPCTIO::rdpftriple(yield_t &yield, nbits_t depth,
 
     MPCPeerIO &mpcpio = static_cast<MPCPeerIO&>(mpcio);
     if (mpcio.mode == MODE_ONLINE) {
-        std::get<WIDTH-1>(mpcpio.rdpftriples)[thread_num][depth-1].get(val);
+        if (incremental) {
+            std::get<WIDTH-1>(mpcpio.irdpftriples)
+                [thread_num][depth-1].get(val);
+        } else {
+            std::get<WIDTH-1>(mpcpio.rdpftriples)
+                [thread_num][depth-1].get(val);
+        }
     } else {
         val = RDPFTriple<WIDTH>(*this, yield, depth,
             incremental, keep_expansion);
         iostream_server() <<
             val.dpf[(mpcio.player == 0) ? 1 : 2];
-        std::get<WIDTH-1>(mpcpio.rdpftriples)[thread_num][depth-1].inc();
+        if (incremental) {
+            std::get<WIDTH-1>(mpcpio.irdpftriples)
+                [thread_num][depth-1].inc();
+        } else {
+            std::get<WIDTH-1>(mpcpio.rdpftriples)
+                [thread_num][depth-1].inc();
+        }
         yield();
     }
     return val;
@@ -85,13 +97,25 @@ RDPFPair<WIDTH> MPCTIO::rdpfpair(yield_t &yield, nbits_t depth,
 
     MPCServerIO &mpcsrvio = static_cast<MPCServerIO&>(mpcio);
     if (mpcio.mode == MODE_ONLINE) {
-        std::get<WIDTH-1>(mpcsrvio.rdpfpairs)[thread_num][depth-1].get(val);
+        if (incremental) {
+            std::get<WIDTH-1>(mpcsrvio.irdpfpairs)
+                [thread_num][depth-1].get(val);
+        } else {
+            std::get<WIDTH-1>(mpcsrvio.rdpfpairs)
+                [thread_num][depth-1].get(val);
+        }
     } else {
         RDPFTriple<WIDTH> trip(*this, yield, depth, incremental, true);
         yield();
         iostream_p0() >> val.dpf[0];
         iostream_p1() >> val.dpf[1];
-        std::get<WIDTH-1>(mpcsrvio.rdpfpairs)[thread_num][depth-1].inc();
+        if (incremental) {
+            std::get<WIDTH-1>(mpcsrvio.irdpfpairs)
+                [thread_num][depth-1].inc();
+        } else {
+            std::get<WIDTH-1>(mpcsrvio.rdpfpairs)
+                [thread_num][depth-1].inc();
+        }
     }
     return val;
 }

+ 23 - 13
preproc.cpp

@@ -78,7 +78,8 @@ void Openfiles::closeall()
 //   0x00: End of preprocessing
 //
 // One byte: subtype (not sent for type == 0x00)
-//   For RAM DPFs, the subtype is the width (0x01 to 0x05)
+//   For RAM DPFs, the subtype is the width (0x01 to 0x05), OR'd with
+//       0x80 if it is an incremental RDPF
 //   Otherwise, it is 0x00
 //
 // Four bytes: number of objects of that type (not sent for type == 0x00)
@@ -159,13 +160,17 @@ void preprocessing_comp(MPCIO &mpcio, const PRACOptions &opts, char **args)
                     }
                 } else if (type >= 0x01 && type <= 0x30) {
                     // RAM DPFs
+                    bool incremental = false;
+                    if (subtype >= 0x80) {
+                        incremental = true;
+                        subtype -= 0x80;
+                    }
                     assert(subtype >= 0x01 && subtype <= 0x05);
-                    char prefix[11];
-                    strcpy(prefix, "rdpf");
+                    char prefix[12];
+                    strcpy(prefix, incremental ? "irdpf" : "rdpf");
                     if (subtype > 1) {
                         sprintf(prefix+strlen(prefix), "%d_", subtype);
                     }
-                    bool incremental = false;
                     auto tripfile = ofiles.open(prefix,
                         mpcio.player, thread_num, type);
                     for (unsigned int i=0; i<num; ++i) {
@@ -362,7 +367,8 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                                 stio.valselecttriple(yield);
                             });
                     }
-                } else if (type[0] == 'r') {
+                } else if (type[0] == 'r' || type[0] == 'i') {
+                    bool incremental = (type[0] == 'i');
                     char *widthstr = strchr(type, '.');
                     unsigned char width = 1;
                     if (widthstr) {
@@ -376,6 +382,9 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                     } else {
                         unsigned char typetag = depth;
                         unsigned char subtypetag = width;
+                        if (incremental) {
+                            subtypetag += 0x80;
+                        }
                         stio.queue_p0(&typetag, 1);
                         stio.queue_p0(&subtypetag, 1);
                         stio.queue_p0(&num, 4);
@@ -383,8 +392,8 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                         stio.queue_p1(&subtypetag, 1);
                         stio.queue_p1(&num, 4);
 
-                        char prefix[11];
-                        strcpy(prefix, "rdpf");
+                        char prefix[12];
+                        strcpy(prefix, incremental ? "irdpf" : "rdpf");
                         if (width > 1) {
                             sprintf(prefix+strlen(prefix), "%d_", width);
                         }
@@ -392,12 +401,13 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                             mpcsrvio.player, thread_num, depth);
                         for (unsigned int i=0; i<num; ++i) {
                             coroutines.emplace_back(
-                                [&stio, &opts, pairfile, depth, width](yield_t &yield) {
+                                [&stio, &opts, pairfile, depth,
+                                incremental, width](yield_t &yield) {
                                     yield();
                                     switch (width) {
                                     case 1: {
                                         RDPFPair<1> rdpfpair =
-                                            stio.rdpfpair<1>(yield, depth);
+                                            stio.rdpfpair<1>(yield, depth, incremental);
                                         if (opts.expand_rdpfs) {
                                             rdpfpair.dpf[0].expand(stio.aes_ops());
                                             rdpfpair.dpf[1].expand(stio.aes_ops());
@@ -407,7 +417,7 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                                     }
                                     case 2: {
                                         RDPFPair<2> rdpfpair =
-                                            stio.rdpfpair<2>(yield, depth);
+                                            stio.rdpfpair<2>(yield, depth, incremental);
                                         if (opts.expand_rdpfs) {
                                             rdpfpair.dpf[0].expand(stio.aes_ops());
                                             rdpfpair.dpf[1].expand(stio.aes_ops());
@@ -417,7 +427,7 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                                     }
                                     case 3: {
                                         RDPFPair<3> rdpfpair =
-                                            stio.rdpfpair<3>(yield, depth);
+                                            stio.rdpfpair<3>(yield, depth, incremental);
                                         if (opts.expand_rdpfs) {
                                             rdpfpair.dpf[0].expand(stio.aes_ops());
                                             rdpfpair.dpf[1].expand(stio.aes_ops());
@@ -427,7 +437,7 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                                     }
                                     case 4: {
                                         RDPFPair<4> rdpfpair =
-                                            stio.rdpfpair<4>(yield, depth);
+                                            stio.rdpfpair<4>(yield, depth, incremental);
                                         if (opts.expand_rdpfs) {
                                             rdpfpair.dpf[0].expand(stio.aes_ops());
                                             rdpfpair.dpf[1].expand(stio.aes_ops());
@@ -437,7 +447,7 @@ void preprocessing_server(MPCServerIO &mpcsrvio, const PRACOptions &opts, char *
                                     }
                                     case 5: {
                                         RDPFPair<5> rdpfpair =
-                                            stio.rdpfpair<5>(yield, depth);
+                                            stio.rdpfpair<5>(yield, depth, incremental);
                                         if (opts.expand_rdpfs) {
                                             rdpfpair.dpf[0].expand(stio.aes_ops());
                                             rdpfpair.dpf[1].expand(stio.aes_ops());

+ 3 - 0
rdpf.hpp

@@ -206,6 +206,9 @@ struct RDPF : public DPF {
         return a;
     }
 
+private:
+    // Expand one leaf layer of the DPF if it's not already expanded
+    void expand_leaf_layer(nbits_t li_index, size_t &aes_ops);
 };
 
 // Computational peers will generate triples of RDPFs with the _same_

+ 24 - 9
rdpf.tcc

@@ -936,17 +936,18 @@ typename RDPF<WIDTH>::LeafNode
     return descend_to_leaf(node, curdepth-1, dir, aes_ops);
 }
 
-// Expand the DPF if it's not already expanded
+// Expand one leaf layer of the DPF if it's not already expanded
 //
-// This routine is slightly more efficient than repeatedly calling
-// StreamEval::next(), but it uses a lot more memory.
+// This routine is slightly more efficient (except for incremental
+// RDPFs) than repeatedly calling StreamEval::next(), but it uses a lot
+// more memory.
 template <nbits_t WIDTH>
-void RDPF<WIDTH>::expand(size_t &aes_ops)
+void RDPF<WIDTH>::expand_leaf_layer(nbits_t li_index, size_t &aes_ops)
 {
-    nbits_t depth = this->depth();
+    nbits_t depth = maxdepth - li_index;
     size_t num_leaves = size_t(1)<<depth;
-    if (li[maxdepth-depth].expansion.size() == num_leaves) return;
-    li[maxdepth-depth].expansion.resize(num_leaves);
+    if (li[li_index].expansion.size() == num_leaves) return;
+    li[li_index].expansion.resize(num_leaves);
     address_t index = 0;
     address_t lastindex = 0;
     DPFnode *path = new DPFnode[depth];
@@ -977,15 +978,29 @@ void RDPF<WIDTH>::expand(size_t &aes_ops)
             path[i+1] = descend(path[i], i, 0, aes_ops);
         }
         lastindex = index;
-        li[maxdepth-depth].expansion[index++] =
+        li[li_index].expansion[index++] =
             descend_to_leaf(path[depth-1], depth-1, 0, aes_ops);
-        li[maxdepth-depth].expansion[index++] =
+        li[li_index].expansion[index++] =
             descend_to_leaf(path[depth-1], depth-1, 1, aes_ops);
     }
 
     delete[] path;
 }
 
+// Expand the DPF if it's not already expanded
+//
+// This routine is slightly more efficient (except for incremental
+// RDPFs) than repeatedly calling StreamEval::next(), but it uses a lot
+// more memory.
+template <nbits_t WIDTH>
+void RDPF<WIDTH>::expand(size_t &aes_ops)
+{
+    nbits_t num_leaf_layers = li.size();
+    for (nbits_t li_index=0; li_index < num_leaf_layers; ++li_index) {
+        expand_leaf_layer(li_index, aes_ops);
+    }
+}
+
 // Construct three RDPFs of the given depth all with the same randomly
 // generated target index.
 template <nbits_t WIDTH>

+ 4 - 0
types.hpp

@@ -748,8 +748,12 @@ struct ValSelectTripleName { static constexpr const char *name = "s"; };
 // header dependencies.
 template <nbits_t WIDTH> struct RDPFPair;
 struct RDPFPairName { static constexpr const char *name = "r"; };
+// Incremental RDPFs
+struct IRDPFPairName { static constexpr const char *name = "i"; };
 template <nbits_t WIDTH> struct RDPFTriple;
 struct RDPFTripleName { static constexpr const char *name = "r"; };
+// Incremental RDPFs
+struct IRDPFTripleName { static constexpr const char *name = "i"; };
 struct CDPF;
 struct CDPFName { static constexpr const char *name = "c"; };