Browse Source

Prepare a unit test for wide DPFs

Ian Goldberg 1 year ago
parent
commit
6684abdad7
5 changed files with 211 additions and 179 deletions
  1. 23 21
      Makefile
  2. 0 90
      mpcio.cpp
  3. 6 2
      mpcio.hpp
  4. 91 0
      mpcio.tcc
  5. 91 66
      online.cpp

+ 23 - 21
Makefile

@@ -31,24 +31,26 @@ depend:
 
 # DO NOT DELETE THIS LINE -- make depend depends on it.
 
-prac.o: mpcio.hpp types.hpp corotypes.hpp preproc.hpp options.hpp online.hpp
-mpcio.o: mpcio.hpp types.hpp corotypes.hpp rdpf.hpp coroutine.hpp
-mpcio.o: bitutils.hpp dpf.hpp prg.hpp aes.hpp rdpf.tcc cdpf.hpp cdpf.tcc
-preproc.o: types.hpp coroutine.hpp corotypes.hpp mpcio.hpp preproc.hpp
-preproc.o: options.hpp rdpf.hpp bitutils.hpp dpf.hpp prg.hpp aes.hpp rdpf.tcc
-preproc.o: cdpf.hpp cdpf.tcc
-online.o: online.hpp mpcio.hpp types.hpp corotypes.hpp options.hpp mpcops.hpp
-online.o: coroutine.hpp rdpf.hpp bitutils.hpp dpf.hpp prg.hpp aes.hpp
-online.o: rdpf.tcc duoram.hpp duoram.tcc cdpf.hpp cdpf.tcc cell.hpp
-mpcops.o: mpcops.hpp types.hpp mpcio.hpp corotypes.hpp coroutine.hpp
-mpcops.o: bitutils.hpp
-rdpf.o: rdpf.hpp mpcio.hpp types.hpp corotypes.hpp coroutine.hpp bitutils.hpp
-rdpf.o: dpf.hpp prg.hpp aes.hpp rdpf.tcc mpcops.hpp
-cdpf.o: bitutils.hpp cdpf.hpp mpcio.hpp types.hpp corotypes.hpp coroutine.hpp
-cdpf.o: dpf.hpp prg.hpp aes.hpp cdpf.tcc
-duoram.o: duoram.hpp types.hpp mpcio.hpp corotypes.hpp coroutine.hpp
-duoram.o: duoram.tcc mpcops.hpp cdpf.hpp dpf.hpp prg.hpp bitutils.hpp aes.hpp
-duoram.o: cdpf.tcc rdpf.hpp rdpf.tcc
-cell.o: types.hpp duoram.hpp mpcio.hpp corotypes.hpp coroutine.hpp duoram.tcc
-cell.o: mpcops.hpp cdpf.hpp dpf.hpp prg.hpp bitutils.hpp aes.hpp cdpf.tcc
-cell.o: rdpf.hpp rdpf.tcc cell.hpp options.hpp
+prac.o: mpcio.hpp types.hpp corotypes.hpp mpcio.tcc preproc.hpp options.hpp
+prac.o: online.hpp
+mpcio.o: mpcio.hpp types.hpp corotypes.hpp mpcio.tcc rdpf.hpp coroutine.hpp
+mpcio.o: bitutils.hpp dpf.hpp prg.hpp aes.hpp rdpf.tcc mpcops.hpp cdpf.hpp
+mpcio.o: cdpf.tcc
+preproc.o: types.hpp coroutine.hpp corotypes.hpp mpcio.hpp mpcio.tcc
+preproc.o: preproc.hpp options.hpp rdpf.hpp bitutils.hpp dpf.hpp prg.hpp
+preproc.o: aes.hpp rdpf.tcc mpcops.hpp cdpf.hpp cdpf.tcc
+online.o: online.hpp mpcio.hpp types.hpp corotypes.hpp mpcio.tcc options.hpp
+online.o: mpcops.hpp coroutine.hpp rdpf.hpp bitutils.hpp dpf.hpp prg.hpp
+online.o: aes.hpp rdpf.tcc duoram.hpp duoram.tcc cdpf.hpp cdpf.tcc cell.hpp
+mpcops.o: mpcops.hpp types.hpp mpcio.hpp corotypes.hpp mpcio.tcc
+mpcops.o: coroutine.hpp bitutils.hpp
+rdpf.o: rdpf.hpp mpcio.hpp types.hpp corotypes.hpp mpcio.tcc coroutine.hpp
+rdpf.o: bitutils.hpp dpf.hpp prg.hpp aes.hpp rdpf.tcc mpcops.hpp
+cdpf.o: bitutils.hpp cdpf.hpp mpcio.hpp types.hpp corotypes.hpp mpcio.tcc
+cdpf.o: coroutine.hpp dpf.hpp prg.hpp aes.hpp cdpf.tcc
+duoram.o: duoram.hpp types.hpp mpcio.hpp corotypes.hpp mpcio.tcc
+duoram.o: coroutine.hpp duoram.tcc mpcops.hpp cdpf.hpp dpf.hpp prg.hpp
+duoram.o: bitutils.hpp aes.hpp cdpf.tcc rdpf.hpp rdpf.tcc
+cell.o: types.hpp duoram.hpp mpcio.hpp corotypes.hpp mpcio.tcc coroutine.hpp
+cell.o: duoram.tcc mpcops.hpp cdpf.hpp dpf.hpp prg.hpp bitutils.hpp aes.hpp
+cell.o: cdpf.tcc rdpf.hpp rdpf.tcc cell.hpp options.hpp

+ 0 - 90
mpcio.cpp

@@ -6,54 +6,6 @@
 #include "bitutils.hpp"
 #include "coroutine.hpp"
 
-// T is the type being stored
-// N is a type whose "name" static member is a string naming the type
-//   so that we can report something useful to the user if they try
-//   to read a type that we don't have any more values for
-template<typename T, typename N>
-PreCompStorage<T,N>::PreCompStorage(unsigned player, ProcessingMode mode,
-        const char *filenameprefix, unsigned thread_num) :
-        name(N::name), depth(0)
-{
-    init(player, mode, filenameprefix, thread_num);
-}
-
-template<typename T, typename N>
-void PreCompStorage<T,N>::init(unsigned player, ProcessingMode mode,
-        const char *filenameprefix, unsigned thread_num, nbits_t depth)
-{
-    if (mode != MODE_ONLINE) return;
-    std::string filename(filenameprefix);
-    char suffix[20];
-    if (depth) {
-        this->depth = depth;
-        sprintf(suffix, "%02d.p%d.t%u", depth, player%10, thread_num);
-    } else {
-        sprintf(suffix, ".p%d.t%u", player%10, thread_num);
-    }
-    filename.append(suffix);
-    storage.open(filename);
-    // It's OK if not every file exists; so don't worry about checking
-    // for errors here.  We'll report an error in get() if we actually
-    // try to use a value for which we don't have a precomputed file.
-    count = 0;
-}
-
-template<typename T, typename N>
-void PreCompStorage<T,N>::get(T& nextval)
-{
-    storage >> nextval;
-    if (!storage.good()) {
-        std::cerr << "Failed to read precomputed value from " << name;
-        if (depth) {
-            std::cerr << (int)depth;
-        }
-        std::cerr << " storage\n";
-        exit(1);
-    }
-    ++count;
-}
-
 void MPCSingleIO::async_send_from_msgqueue()
 {
 #ifdef SEND_LAMPORT_CLOCKS
@@ -800,48 +752,6 @@ SelectTriple<bit_t> MPCTIO::bitselecttriple(yield_t &yield)
     return val;
 }
 
-// Only computational peers call this; the server should be calling
-// rdpfpair() at the same time
-RDPFTriple<1> MPCTIO::rdpftriple(yield_t &yield, nbits_t depth,
-    bool keep_expansion)
-{
-    assert(mpcio.player < 2);
-    RDPFTriple<1> val;
-
-    MPCPeerIO &mpcpio = static_cast<MPCPeerIO&>(mpcio);
-    if (mpcio.mode == MODE_ONLINE) {
-        mpcpio.rdpftriples[thread_num][depth-1].get(val);
-    } else {
-        val = RDPFTriple<1>(*this, yield, depth,
-            keep_expansion);
-        iostream_server() <<
-            val.dpf[(mpcio.player == 0) ? 1 : 2];
-        mpcpio.rdpftriples[thread_num][depth-1].inc();
-        yield();
-    }
-    return val;
-}
-
-// Only the server calls this; the computational peers should be calling
-// rdpftriple() at the same time
-RDPFPair<1> MPCTIO::rdpfpair(yield_t &yield, nbits_t depth)
-{
-    assert(mpcio.player == 2);
-    RDPFPair<1> val;
-
-    MPCServerIO &mpcsrvio = static_cast<MPCServerIO&>(mpcio);
-    if (mpcio.mode == MODE_ONLINE) {
-        mpcsrvio.rdpfpairs[thread_num][depth-1].get(val);
-    } else {
-        RDPFTriple<1> trip(*this, yield, depth, true);
-        yield();
-        iostream_p0() >> val.dpf[0];
-        iostream_p1() >> val.dpf[1];
-        mpcsrvio.rdpfpairs[thread_num][depth-1].inc();
-    }
-    return val;
-}
-
 CDPF MPCTIO::cdpf(yield_t &yield)
 {
     CDPF val;

+ 6 - 2
mpcio.hpp

@@ -387,10 +387,12 @@ public:
 
     // These ones only work during the online phase
     // Computational peers call:
-    RDPFTriple<1> rdpftriple(yield_t &yield, nbits_t depth,
+    template <nbits_t WIDTH = 1>
+    RDPFTriple<WIDTH> rdpftriple(yield_t &yield, nbits_t depth,
         bool keep_expansion = true);
     // The server calls:
-    RDPFPair<1> rdpfpair(yield_t &yield, nbits_t depth);
+    template <nbits_t WIDTH = 1>
+    RDPFPair<WIDTH> rdpfpair(yield_t &yield, nbits_t depth);
     // Anyone can call:
     CDPF cdpf(yield_t &yield);
 
@@ -438,4 +440,6 @@ void mpcio_setup_server(boost::asio::io_context &io_context,
     std::deque<tcp::socket> &p0socks,
     std::deque<tcp::socket> &p1socks);
 
+#include "mpcio.tcc"
+
 #endif

+ 91 - 0
mpcio.tcc

@@ -0,0 +1,91 @@
+// T is the type being stored
+// N is a type whose "name" static member is a string naming the type
+//   so that we can report something useful to the user if they try
+//   to read a type that we don't have any more values for
+template<typename T, typename N>
+PreCompStorage<T,N>::PreCompStorage(unsigned player, ProcessingMode mode,
+        const char *filenameprefix, unsigned thread_num) :
+        name(N::name), depth(0)
+{
+    init(player, mode, filenameprefix, thread_num);
+}
+
+template<typename T, typename N>
+void PreCompStorage<T,N>::init(unsigned player, ProcessingMode mode,
+        const char *filenameprefix, unsigned thread_num, nbits_t depth)
+{
+    if (mode != MODE_ONLINE) return;
+    std::string filename(filenameprefix);
+    char suffix[20];
+    if (depth) {
+        this->depth = depth;
+        sprintf(suffix, "%02d.p%d.t%u", depth, player%10, thread_num);
+    } else {
+        sprintf(suffix, ".p%d.t%u", player%10, thread_num);
+    }
+    filename.append(suffix);
+    storage.open(filename);
+    // It's OK if not every file exists; so don't worry about checking
+    // for errors here.  We'll report an error in get() if we actually
+    // try to use a value for which we don't have a precomputed file.
+    count = 0;
+}
+
+template<typename T, typename N>
+void PreCompStorage<T,N>::get(T& nextval)
+{
+    storage >> nextval;
+    if (!storage.good()) {
+        std::cerr << "Failed to read precomputed value from " << name;
+        if (depth) {
+            std::cerr << (int)depth;
+        }
+        std::cerr << " storage\n";
+        exit(1);
+    }
+    ++count;
+}
+
+// Only computational peers call this; the server should be calling
+// rdpfpair() at the same time
+template <nbits_t WIDTH>
+RDPFTriple<WIDTH> MPCTIO::rdpftriple(yield_t &yield, nbits_t depth,
+    bool keep_expansion)
+{
+    assert(mpcio.player < 2);
+    RDPFTriple<WIDTH> val;
+
+    MPCPeerIO &mpcpio = static_cast<MPCPeerIO&>(mpcio);
+    if (mpcio.mode == MODE_ONLINE) {
+        mpcpio.rdpftriples[thread_num][depth-1].get(val);
+    } else {
+        val = RDPFTriple<WIDTH>(*this, yield, depth,
+            keep_expansion);
+        iostream_server() <<
+            val.dpf[(mpcio.player == 0) ? 1 : 2];
+        mpcpio.rdpftriples[thread_num][depth-1].inc();
+        yield();
+    }
+    return val;
+}
+
+// Only the server calls this; the computational peers should be calling
+// rdpftriple() at the same time
+template <nbits_t WIDTH>
+RDPFPair<WIDTH> MPCTIO::rdpfpair(yield_t &yield, nbits_t depth)
+{
+    assert(mpcio.player == 2);
+    RDPFPair<WIDTH> val;
+
+    MPCServerIO &mpcsrvio = static_cast<MPCServerIO&>(mpcio);
+    if (mpcio.mode == MODE_ONLINE) {
+        mpcsrvio.rdpfpairs[thread_num][depth-1].get(val);
+    } else {
+        RDPFTriple<WIDTH> trip(*this, yield, depth, true);
+        yield();
+        iostream_p0() >> val.dpf[0];
+        iostream_p1() >> val.dpf[1];
+        mpcsrvio.rdpfpairs[thread_num][depth-1].inc();
+    }
+    return val;
+}

+ 91 - 66
online.cpp

@@ -192,6 +192,7 @@ static void lamport_test(MPCIO &mpcio,
     pool.join();
 }
 
+template <nbits_t WIDTH>
 static void rdpf_test(MPCIO &mpcio,
     const PRACOptions &opts, char **args)
 {
@@ -207,79 +208,89 @@ static void rdpf_test(MPCIO &mpcio,
         ++args;
     }
 
-    int num_threads = opts.num_threads;
-    boost::asio::thread_pool pool(num_threads);
-    for (int thread_num = 0; thread_num < num_threads; ++thread_num) {
-        boost::asio::post(pool, [&mpcio, thread_num, depth, num_iters] {
-            MPCTIO tio(mpcio, thread_num);
-            run_coroutines(tio, [&tio, depth, num_iters] (yield_t &yield) {
-                size_t &aes_ops = tio.aes_ops();
-                for (size_t iter=0; iter < num_iters; ++iter) {
-                    if (tio.player() == 2) {
-                        RDPFPair<1> dp = tio.rdpfpair(yield, depth);
-                        for (int i=0;i<2;++i) {
-                            const RDPF<1> &dpf = dp.dpf[i];
-                            for (address_t x=0;x<(address_t(1)<<depth);++x) {
-                                RDPF<1>::LeafNode leaf = dpf.leaf(x, aes_ops);
-                                RegBS ub = dpf.unit_bs(leaf);
-                                RegAS ua = dpf.unit_as(leaf);
-                                RDPF<1>::RegXSW sx = dpf.scaled_xs(leaf);
-                                RDPF<1>::RegASW sa = dpf.scaled_as(leaf);
-                                printf("%04x %x %016lx %016lx %016lx\n", x,
-                                    ub.bshare, ua.ashare, sx[0].xshare, sa[0].ashare);
-                            }
-                            printf("\n");
+    MPCTIO tio(mpcio, 0, opts.num_threads);
+    run_coroutines(tio, [&tio, depth, num_iters] (yield_t &yield) {
+        size_t &aes_ops = tio.aes_ops();
+        for (size_t iter=0; iter < num_iters; ++iter) {
+            if (tio.player() == 2) {
+                RDPFPair<WIDTH> dp = tio.rdpfpair<WIDTH>(yield, depth);
+                for (int i=0;i<2;++i) {
+                    const RDPF<WIDTH> &dpf = dp.dpf[i];
+                    for (address_t x=0;x<(address_t(1)<<depth);++x) {
+                        typename RDPF<WIDTH>::LeafNode leaf = dpf.leaf(x, aes_ops);
+                        RegBS ub = dpf.unit_bs(leaf);
+                        RegAS ua = dpf.unit_as(leaf);
+                        typename RDPF<WIDTH>::RegXSW sx = dpf.scaled_xs(leaf);
+                        typename RDPF<WIDTH>::RegASW sa = dpf.scaled_as(leaf);
+                        printf("%04x %x %016lx", x, ub.bshare, ua.ashare);
+                        for (nbits_t j=0;j<WIDTH;++j) {
+                            printf(" %016lx %016lx", sx[j].xshare, sa[j].ashare);
                         }
+                        printf("\n");
+                    }
+                    printf("\n");
+                }
+            } else {
+                RDPFTriple<WIDTH> dt = tio.rdpftriple<WIDTH>(yield, depth);
+                for (int i=0;i<3;++i) {
+                    const RDPF<WIDTH> &dpf = dt.dpf[i];
+                    typename RDPF<WIDTH>::RegXSW peer_scaled_xor;
+                    typename RDPF<WIDTH>::RegASW peer_scaled_sum;
+                    if (tio.player() == 1) {
+                        tio.iostream_peer() << dpf.li[0].scaled_xor << dpf.li[0].scaled_sum;
                     } else {
-                        RDPFTriple<1> dt = tio.rdpftriple(yield, depth);
-                        for (int i=0;i<3;++i) {
-                            const RDPF<1> &dpf = dt.dpf[i];
-                            RegXS peer_scaled_xor;
-                            RegAS peer_scaled_sum;
-                            if (tio.player() == 1) {
-                                tio.iostream_peer() << dpf.li[0].scaled_xor[0] << dpf.li[0].scaled_sum[0];
-                            } else {
-                                tio.iostream_peer() >> peer_scaled_xor >> peer_scaled_sum;
-                                peer_scaled_sum += dpf.li[0].scaled_sum[0];
-                                peer_scaled_xor ^= dpf.li[0].scaled_xor[0];
+                        tio.iostream_peer() >> peer_scaled_xor >> peer_scaled_sum;
+                        peer_scaled_sum += dpf.li[0].scaled_sum;
+                        peer_scaled_xor ^= dpf.li[0].scaled_xor;
+                    }
+                    for (address_t x=0;x<(address_t(1)<<depth);++x) {
+                        typename RDPF<WIDTH>::LeafNode leaf = dpf.leaf(x, aes_ops);
+                        RegBS ub = dpf.unit_bs(leaf);
+                        RegAS ua = dpf.unit_as(leaf);
+                        typename RDPF<WIDTH>::RegXSW sx = dpf.scaled_xs(leaf);
+                        typename RDPF<WIDTH>::RegASW sa = dpf.scaled_as(leaf);
+                        printf("%04x %x %016lx", x, ub.bshare, ua.ashare);
+                        for (nbits_t j=0;j<WIDTH;++j) {
+                            printf(" %016lx %016lx", sx[j].xshare, sa[j].ashare);
+                        }
+                        printf("\n");
+                        if (tio.player() == 1) {
+                            tio.iostream_peer() << ub << ua << sx << sa;
+                        } else {
+                            RegBS peer_ub;
+                            RegAS peer_ua;
+                            typename RDPF<WIDTH>::RegXSW peer_sx;
+                            typename RDPF<WIDTH>::RegASW peer_sa;
+                            tio.iostream_peer() >> peer_ub >> peer_ua >>
+                                peer_sx >> peer_sa;
+                            ub ^= peer_ub;
+                            ua += peer_ua;
+                            sx ^= peer_sx;
+                            sa += peer_sa;
+                            bool is_nonzero = ub.bshare || ua.ashare;
+                            for (nbits_t j=0;j<WIDTH;++j) {
+                                is_nonzero |= (sx[j].xshare || sa[j].ashare);
                             }
-                            for (address_t x=0;x<(address_t(1)<<depth);++x) {
-                                RDPF<1>::LeafNode leaf = dpf.leaf(x, aes_ops);
-                                RegBS ub = dpf.unit_bs(leaf);
-                                RegAS ua = dpf.unit_as(leaf);
-                                RDPF<1>::RegXSW sx = dpf.scaled_xs(leaf);
-                                RDPF<1>::RegASW sa = dpf.scaled_as(leaf);
-                                printf("%04x %x %016lx %016lx %016lx\n", x,
-                                    ub.bshare, ua.ashare, sx[0].xshare, sa[0].ashare);
-                                if (tio.player() == 1) {
-                                    tio.iostream_peer() << ub << ua << sx << sa;
-                                } else {
-                                    RegBS peer_ub;
-                                    RegAS peer_ua;
-                                    RDPF<1>::RegXSW peer_sx;
-                                    RDPF<1>::RegASW peer_sa;
-                                    tio.iostream_peer() >> peer_ub >> peer_ua >>
-                                        peer_sx >> peer_sa;
-                                    ub ^= peer_ub;
-                                    ua += peer_ua;
-                                    sx ^= peer_sx;
-                                    sa += peer_sa;
-                                    if (ub.bshare || ua.ashare || sx[0].xshare || sa[0].ashare) {
-                                        printf("**** %x %016lx %016lx %016lx\n",
-                                            ub.bshare, ua.ashare, sx[0].xshare, sa[0].ashare);
-                                        printf("SCALE                   %016lx %016lx\n",
-                                            peer_scaled_xor.xshare, peer_scaled_sum.ashare);
-                                    }
+                            if (is_nonzero) {
+                                printf("**** %x %016lx", ub.bshare, ua.ashare);
+                                for (nbits_t j=0;j<WIDTH;++j) {
+                                    printf(" %016lx %016lx", sx[j].xshare, sa[j].ashare);
+                                }
+                                printf("\nSCALE                  ");
+                                for (nbits_t j=0;j<WIDTH;++j) {
+                                    printf(" %016lx %016lx",
+                                        peer_scaled_xor[j].xshare,
+                                        peer_scaled_sum[j].ashare);
                                 }
+                                printf("\n");
                             }
-                            printf("\n");
                         }
                     }
+                    printf("\n");
                 }
-            });
-        });
-    }
-    pool.join();
+            }
+        }
+    });
 }
 
 static void rdpf_timing(MPCIO &mpcio,
@@ -1165,7 +1176,21 @@ void online_main(MPCIO &mpcio, const PRACOptions &opts, char **args)
         lamport_test(mpcio, opts, args);
     } else if (!strcmp(*args, "rdpftest")) {
         ++args;
-        rdpf_test(mpcio, opts, args);
+        rdpf_test<1>(mpcio, opts, args);
+/*
+    } else if (!strcmp(*args, "rdpftest2")) {
+        ++args;
+        rdpf_test<2>(mpcio, opts, args);
+    } else if (!strcmp(*args, "rdpftest3")) {
+        ++args;
+        rdpf_test<3>(mpcio, opts, args);
+    } else if (!strcmp(*args, "rdpftest4")) {
+        ++args;
+        rdpf_test<4>(mpcio, opts, args);
+    } else if (!strcmp(*args, "rdpftest5")) {
+        ++args;
+        rdpf_test<5>(mpcio, opts, args);
+*/
     } else if (!strcmp(*args, "rdpftime")) {
         ++args;
         rdpf_timing(mpcio, opts, args);