Skip to content

Commit 92b62ea

Browse files
committed
chore: rayonize MPC mult
1 parent 9ba889b commit 92b62ea

File tree

1 file changed

+53
-49
lines changed

1 file changed

+53
-49
lines changed

core/threshold/src/execution/online/triple.rs

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use crate::{
22
algebra::structure_traits::{ErrorCorrect, Ring},
3-
error::error_handler::{anyhow_error_and_log, log_error_wrapper},
3+
error::error_handler::anyhow_error_and_log,
44
execution::{
55
runtime::session::BaseSessionHandles,
66
sharing::{
77
open::{RobustOpen, SecureRobustOpen},
88
share::Share,
99
},
1010
},
11+
thread_handles::spawn_compute_bound,
1112
};
12-
use anyhow::Context;
1313
use itertools::Itertools;
1414
use serde::{Deserialize, Serialize};
1515
use tracing::instrument;
@@ -74,57 +74,61 @@ pub async fn mult_list<Z: Ring + ErrorCorrect, Ses: BaseSessionHandles>(
7474
triples.len()
7575
)));
7676
}
77-
let mut to_open = Vec::with_capacity(2 * amount);
78-
// Compute the shares of epsilon and rho and merge them together into a single list
79-
for ((cur_x, cur_y), cur_trip) in x_vec.iter().zip_eq(y_vec).zip_eq(&triples) {
80-
if cur_x.owner() != cur_y.owner()
81-
|| cur_trip.a.owner() != cur_x.owner()
82-
|| cur_trip.b.owner() != cur_x.owner()
83-
|| cur_trip.c.owner() != cur_x.owner()
84-
{
85-
tracing::warn!("Trying to multiply with shares of different owners. This will always result in an incorrect share");
86-
}
87-
let share_epsilon = cur_trip.a + *cur_x;
88-
let share_rho = cur_trip.b + *cur_y;
89-
to_open.push(share_epsilon);
90-
to_open.push(share_rho);
91-
}
77+
let x_vec_cloned = x_vec.to_owned();
78+
let y_vec_cloned = y_vec.to_owned();
79+
let (triples_a, (triples_b, triples_c)): (Vec<_>, (Vec<_>, Vec<_>)) = triples
80+
.into_iter()
81+
.map(|triple| (triple.a, (triple.b, triple.c)))
82+
.unzip();
83+
84+
let triples_a_cloned = triples_a.clone();
85+
let to_open: Vec<Share<Z>> = spawn_compute_bound(move || {
86+
x_vec_cloned.into_iter().zip_eq(
87+
y_vec_cloned
88+
.into_iter()
89+
.zip(triples_a_cloned.into_iter().zip_eq(triples_b.into_iter())),
90+
).fold(Vec::with_capacity(2*amount), |mut acc, (cur_x, (cur_y, (cur_a, cur_b)))| {
91+
if cur_x.owner() != cur_y.owner()
92+
|| cur_a.owner() != cur_x.owner()
93+
|| cur_b.owner() != cur_x.owner()
94+
{
95+
tracing::warn!("Trying to multiply with shares of different owners. This will always result in an incorrect share");
96+
}
97+
let share_epsilon = cur_a + cur_x;
98+
let share_rho = cur_b + cur_y;
99+
acc.push(share_epsilon);
100+
acc.push(share_rho);
101+
acc
102+
})
103+
}).await?;
104+
92105
//NOTE: That's a lot of memory manipulation, could execute the "linear equation loop" with epsilonrho directly
93106
// Open and seperate the list of both epsilon and rho values into two lists of values
94-
let mut epsilonrho = open_list(&to_open, session).await?;
95-
let mut epsilon_vec = Vec::with_capacity(amount);
96-
let mut rho_vec = Vec::with_capacity(amount);
97-
// Indicator variable if the current element is an epsilson value (or rho value)
98-
let mut epsilon_val = false;
99-
// Go through the list from the back
100-
while let Some(cur_val) = epsilonrho.pop() {
101-
match epsilon_val {
102-
true => epsilon_vec.push(cur_val),
103-
false => rho_vec.push(cur_val),
104-
}
105-
// Flip the indicator
106-
epsilon_val = !epsilon_val;
107+
let epsilonrho = open_list(&to_open, session).await?;
108+
109+
if 2 * amount != epsilonrho.len() {
110+
return Err(anyhow_error_and_log(format!(
111+
"Inconsistent share lengths: epsilonrho_vec: {:?}. Expected {:?}",
112+
epsilonrho.len(),
113+
2 * amount
114+
)));
107115
}
108116
// Compute the linear equation of shares to get the result
109-
let mut res = Vec::with_capacity(amount);
110-
for i in 0..amount {
111-
let y = *y_vec
112-
.get(i)
113-
.with_context(|| log_error_wrapper("Missing y value"))?;
114-
// Observe that the list of epsilons and rhos have already been reversed above, because of the use of pop,
115-
// so we get the elements in the original order by popping again here
116-
let epsilon = epsilon_vec
117-
.pop()
118-
.with_context(|| log_error_wrapper("Missing epsilon value"))?;
119-
let rho = rho_vec
120-
.pop()
121-
.with_context(|| log_error_wrapper("Missing rho value"))?;
122-
let trip = triples
123-
.get(i)
124-
.with_context(|| log_error_wrapper("Missing triple"))?;
125-
res.push(y * epsilon - trip.a * rho + trip.c);
126-
}
127-
Ok(res)
117+
let y_vec_cloned = y_vec.to_owned();
118+
119+
spawn_compute_bound(move || {
120+
let epsilon_rho_vec = epsilonrho.chunks(2);
121+
y_vec_cloned
122+
.into_iter()
123+
.zip_eq(epsilon_rho_vec.zip_eq(triples_a.into_iter().zip_eq(triples_c.into_iter())))
124+
.map(|(curr_y, (curr_epsilonrho, (curr_a, curr_c)))| {
125+
//curr_epsilonrho is a pair of shares, so we need to extract them
126+
//first is epsilon then rho
127+
curr_y * curr_epsilonrho[0] - curr_a * curr_epsilonrho[1] + curr_c
128+
})
129+
.collect()
130+
})
131+
.await
128132
}
129133

130134
/// Opens a single secret

0 commit comments

Comments
 (0)