Checkpoint the party/runtime stack before share-program and malicious-mode work.
Ship the TLS mesh, composer, Beaver/Yao/leaf MPC, prep/online paths, apps, and docs so the tree is pushable before elevating share_expr, security_mode, and prep resume. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
695f8e84f7
commit
0d22946a0e
1835 changed files with 170291 additions and 2849 deletions
222
examples/applications/experiment_bench.cpp
Normal file
222
examples/applications/experiment_bench.cpp
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "dpf/app_flow.hpp"
|
||||
#include "dpf/app_plans.hpp"
|
||||
#include "dpf/bench_cells.hpp"
|
||||
#include "dpf/experiment.hpp"
|
||||
#include "dpf/party_runner.hpp"
|
||||
#include "dpf/run_log.hpp"
|
||||
|
||||
// Every cell is a compose plan driven by `run_parties` on one `run_config`:
|
||||
// the party mesh over in-process async memory, unix sockets, TCP mux, parallel
|
||||
// TCP, or SCTP. `memory` and `stream` are the older paired sinks; this harness
|
||||
// uses the mesh, so those two names run as async. Every `run_config` key is a
|
||||
// flag (`--transport=mux --lanes=4 --window=262144 --warmup=2 --trials=9`) or
|
||||
// the matching `DPF_*` variable; flags win. Lanes default to 1 here. Each cell
|
||||
// runs `warmup` untimed and `trials` timed repetitions and records every
|
||||
// party's trial times, party 0's and the slowest party's medians, the
|
||||
// configuration, and party 0's wire counters in the CSVs. Every repetition
|
||||
// draws from streams derived from the cell's master, so replaying the master
|
||||
// replays the cell.
|
||||
//
|
||||
// c++ -std=c++17 -march=native -pthread -I include -I thirdparty \
|
||||
// examples/applications/experiment_bench.cpp -lsctp
|
||||
// DPF_EXPERIMENT_DIR=/tmp/libdpf_bench ./a.out --transport=mux --trials=5
|
||||
//
|
||||
// The first block is the DPF plans. The second block is the work that is not
|
||||
// a key: word gadgets, stacked branches, short tables, and a hidden reorder
|
||||
// of a column the parties already share.
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
dpf::app::run_config mesh_config(int argc, char ** argv, std::string & replaced)
|
||||
{
|
||||
dpf::app::run_config cfg;
|
||||
cfg.n_lanes = 1;
|
||||
cfg.merge_env();
|
||||
const auto rest = cfg.apply_args(argc, argv);
|
||||
if (!rest.empty())
|
||||
throw std::invalid_argument("unexpected argument '" + rest.front()
|
||||
+ "' (flags are --key=value)");
|
||||
if (cfg.kind == dpf::net::transport::memory_sink
|
||||
|| cfg.kind == dpf::net::transport::memory_stream)
|
||||
{
|
||||
std::cout << "transport "
|
||||
<< dpf::net::transport_name(cfg.kind)
|
||||
<< " is a paired sink; the battery uses the party mesh (async)\n";
|
||||
replaced = dpf::net::transport_name(cfg.kind);
|
||||
cfg.kind = dpf::net::transport::async_memory;
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
int measure_plans(const char * name, std::vector<dpf::protocol::plan> plans,
|
||||
std::uint64_t run_id, const std::string & dir, const dpf::app::run_config & cfg,
|
||||
dpf::protocol::cell_fn cell)
|
||||
{
|
||||
if (plans.empty() || plans[0].rounds() == 0)
|
||||
{
|
||||
std::cerr << name << " has no exchange rounds\n";
|
||||
return 1;
|
||||
}
|
||||
dpf::experiment ex(name, "p0");
|
||||
ex.set_run_id(run_id);
|
||||
ex.ingest_plan(plans[0]);
|
||||
ex.set_config(cfg.describe());
|
||||
dpf::app::parties_result result;
|
||||
const std::size_t total = cfg.warmup + std::max<std::size_t>(1, cfg.trials);
|
||||
try
|
||||
{
|
||||
for (std::size_t t = 0; t < total; ++t)
|
||||
{
|
||||
std::vector<dpf::app::party_values> values(plans.size());
|
||||
const bool last = t + 1 == total;
|
||||
result = dpf::app::run_parties(plans, values, {}, cfg,
|
||||
last ? &ex : nullptr, cell, &ex);
|
||||
if (t >= cfg.warmup)
|
||||
ex.add_trial(result.party0_wall_ns, result.party_wall_ns);
|
||||
}
|
||||
}
|
||||
catch (const std::exception & err)
|
||||
{
|
||||
std::cerr << name << " flow: " << err.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
const auto wire = result.wire.empty() ? dpf::net::stream_stats{} : result.wire[0];
|
||||
dpf::experiment::wire_counts w;
|
||||
w.bytes_out = wire.bytes_out;
|
||||
w.bytes_in = wire.bytes_in;
|
||||
w.payload_out = wire.payload_out;
|
||||
w.payload_in = wire.payload_in;
|
||||
w.frames_out = wire.frames_out;
|
||||
w.frames_in = wire.frames_in;
|
||||
w.write_calls = wire.write_calls;
|
||||
ex.set_wire(w);
|
||||
ex.write_csv(dir);
|
||||
std::cout << name << " parties=" << plans.size()
|
||||
<< " run_id=" << run_id
|
||||
<< " rounds=" << ex.interactive_rounds()
|
||||
<< " bytes=" << ex.plan_bytes_out()
|
||||
<< " wire_out=" << wire.bytes_out
|
||||
<< " wire_in=" << wire.bytes_in
|
||||
<< " payload_out=" << wire.payload_out
|
||||
<< " median_ns=" << ex.median_trial_ns()
|
||||
<< " slowest_median_ns=" << ex.slowest_median_ns()
|
||||
<< " trials=" << ex.trials().size()
|
||||
<< " prg_evals=" << ex.prg_evals()
|
||||
<< " seed=" << ex.seed_hex() << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
const char * env = std::getenv("DPF_EXPERIMENT_DIR");
|
||||
const std::string dir = (env && env[0] != '\0') ? env
|
||||
: "/tmp/libdpf_experiment_bench";
|
||||
dpf::app::run_config cfg;
|
||||
std::string replaced;
|
||||
try
|
||||
{
|
||||
cfg = mesh_config(argc, argv, replaced);
|
||||
dpf::app::start_logging(cfg);
|
||||
}
|
||||
catch (const std::exception & err)
|
||||
{
|
||||
std::cerr << "experiment_bench: " << err.what() << "\n";
|
||||
return 2;
|
||||
}
|
||||
if (!replaced.empty())
|
||||
DPF_LOG(warning, "config.override").kv("key", "transport")
|
||||
.kv("requested", replaced).kv("used", "async")
|
||||
.kv("detail", "paired sinks cannot carry the party mesh");
|
||||
std::cout << cfg.summary() << "\n";
|
||||
|
||||
struct named
|
||||
{
|
||||
const char * name;
|
||||
int parties;
|
||||
dpf::protocol::plan (*make)(std::size_t party);
|
||||
};
|
||||
const named dpf_plans[] = {
|
||||
{"keyword_pir", 2, [](std::size_t p) {
|
||||
return dpf::protocol::keyword_pir_compose_plan(p, 8);
|
||||
}},
|
||||
{"express", 2, [](std::size_t p) {
|
||||
return dpf::protocol::mailbox_write_fused_plan(p);
|
||||
}},
|
||||
{"subleq", 2, [](std::size_t p) {
|
||||
return dpf::protocol::subleq_instruction_plan(p);
|
||||
}},
|
||||
{"pika", 2, [](std::size_t p) {
|
||||
return dpf::protocol::pika_lookup_plan(p);
|
||||
}},
|
||||
{"duoram3", 2, [](std::size_t p) {
|
||||
return dpf::protocol::duoram_update_plan(p);
|
||||
}},
|
||||
{"poplar", 2, [](std::size_t p) {
|
||||
return dpf::protocol::poplar_prefix_plan(p);
|
||||
}},
|
||||
{"poplar_fan4", 2, [](std::size_t p) {
|
||||
return dpf::protocol::poplar_prefix_fan_plan(p, 4);
|
||||
}},
|
||||
{"ledger23", 2, [](std::size_t p) {
|
||||
return dpf::protocol::ledger23_append_plan(p);
|
||||
}},
|
||||
{"bitmore", 2, [](std::size_t p) {
|
||||
return dpf::protocol::bitmore_fan_plan(p);
|
||||
}},
|
||||
{"floram", 2, [](std::size_t p) {
|
||||
return dpf::protocol::floram_ds_plan(p);
|
||||
}},
|
||||
{"fss_point", 2, [](std::size_t p) {
|
||||
return dpf::protocol::fss_point_plan(p);
|
||||
}},
|
||||
{"fss_cmp", 2, [](std::size_t p) {
|
||||
return dpf::protocol::fss_cmp_plan(p);
|
||||
}},
|
||||
{"range_count", 2, [](std::size_t p) {
|
||||
return dpf::protocol::range_count_plan(p);
|
||||
}},
|
||||
{"psi_cuckoo", 2, [](std::size_t p) {
|
||||
return dpf::protocol::psi_cuckoo_plan(p, {0, 2, 5, 7});
|
||||
}},
|
||||
{"idpf_agg", 2, [](std::size_t p) {
|
||||
return dpf::protocol::idpf_agg_plan(p, 8);
|
||||
}},
|
||||
};
|
||||
|
||||
std::uint64_t run_id = 0;
|
||||
for (const auto & row : dpf_plans)
|
||||
{
|
||||
std::vector<dpf::protocol::plan> plans;
|
||||
plans.reserve(static_cast<std::size_t>(row.parties));
|
||||
for (int p = 0; p < row.parties; ++p)
|
||||
plans.push_back(row.make(static_cast<std::size_t>(p)));
|
||||
if (int rc = measure_plans(row.name, std::move(plans), run_id++, dir, cfg,
|
||||
nullptr))
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (const auto & cell : dpf::bench::battery())
|
||||
{
|
||||
std::vector<dpf::protocol::plan> plans;
|
||||
plans.reserve(static_cast<std::size_t>(cell.parties));
|
||||
for (int p = 0; p < cell.parties; ++p)
|
||||
plans.push_back(dpf::bench::plan_for(static_cast<std::size_t>(p), cell.id));
|
||||
if (int rc = measure_plans(cell.name, std::move(plans), run_id++, dir, cfg,
|
||||
&dpf::bench::run_cell))
|
||||
return rc;
|
||||
}
|
||||
std::cout << "wrote CSVs under " << dir << "\n";
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue