Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 11 additions & 32 deletions tfhe/src/core_crypto/commons/math/ntt/ntt64.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::core_crypto::commons::ciphertext_modulus::CiphertextModulusKind;
use crate::core_crypto::commons::plan::new_from_plan_map;
use crate::core_crypto::commons::utils::izip_eq;
use crate::core_crypto::prelude::*;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::sync::{Arc, OnceLock, RwLock};
use tfhe_ntt::prime64::Plan;
Expand All @@ -24,8 +24,10 @@ impl Ntt64 {
}

// Key is (polynomial size, modulus).
type PlanMap = RwLock<HashMap<(usize, u64), Arc<OnceLock<Arc<Plan>>>>>;
type PlanMap = crate::core_crypto::commons::plan::PlanMap<(usize, u64), Plan>;

pub(crate) static PLANS: OnceLock<PlanMap> = OnceLock::new();

fn plans() -> &'static PlanMap {
PLANS.get_or_init(|| RwLock::new(HashMap::new()))
}
Expand All @@ -39,39 +41,16 @@ impl Ntt64 {

let n = size.0;
let modulus = modulus.get_custom_modulus() as u64;
let get_plan = || {
let plans = global_plans.read().unwrap();
let plan = plans.get(&(n, modulus)).cloned();
drop(plans);

plan.map(|p| {
p.get_or_init(|| {
Arc::new(Plan::try_new(n, modulus).unwrap_or_else(|| {
panic!("could not generate an NTT plan for the given (size, modulus) ({n}, {modulus})")
}))
})
.clone()
let plan = new_from_plan_map(global_plans, (n, modulus), |(n, modulus)| {
Plan::try_new(n, modulus).unwrap_or_else(|| {
panic!(
"could not generate an NTT plan for the given (size, modulus) ({n}, {modulus})"
)
})
};

get_plan().map_or_else(
|| {
// If we don't find a plan for the given polynomial size and modulus, we insert a
// new OnceLock, drop the write lock on the map and then let
// get_plan() initialize the OnceLock (without holding the write
// lock on the map).
let mut plans = global_plans.write().unwrap();
if let Entry::Vacant(v) = plans.entry((n, modulus)) {
v.insert(Arc::new(OnceLock::new()));
}
drop(plans);
});

Self {
plan: get_plan().unwrap(),
}
},
|plan| Self { plan },
)
Self { plan }
}
}

Expand Down
1 change: 1 addition & 0 deletions tfhe/src/core_crypto/commons/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod math;
pub mod noise_formulas;
pub mod numeric;
pub mod parameters;
pub mod plan;
pub mod utils;

// Refactor modules
Expand Down
31 changes: 31 additions & 0 deletions tfhe/src/core_crypto/commons/plan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::{Arc, RwLock};

pub type PlanMap<Key, Value> = RwLock<HashMap<Key, Arc<Value>>>;

pub fn new_from_plan_map<Key: Eq + Hash + Copy, Value>(
values_map: &PlanMap<Key, Value>,
key: Key,
new_value: impl Fn(Key) -> Value,
) -> Arc<Value> {
let values = values_map.read().unwrap();

let value = values.get(&key).cloned();
drop(values);

value.unwrap_or_else(|| {
// If we don't find a plan for the given polynomial size and modulus, we insert a
// new one (if we still don't find it after getting a write lock)

let new_value = Arc::new(new_value(key));

let mut values = values_map.write().unwrap();

let value = Arc::clone(values.entry(key).or_insert(new_value));

drop(values);

value
})
}
35 changes: 6 additions & 29 deletions tfhe/src/core_crypto/fft_impl/fft128/math/fft/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::numeric::{CastFrom, CastInto, UnsignedInteger};
use crate::core_crypto::commons::parameters::PolynomialSize;
use crate::core_crypto::commons::plan::new_from_plan_map;
use crate::core_crypto::commons::utils::izip_eq;
use core::any::TypeId;
use dyn_stack::{PodStack, StackReq};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::sync::{Arc, OnceLock, RwLock};
use tfhe_fft::fft128::{f128, Plan};
Expand Down Expand Up @@ -46,7 +46,8 @@ impl Fft128 {
}
}

type PlanMap = RwLock<HashMap<usize, Arc<OnceLock<Arc<PlanWrapper>>>>>;
type PlanMap = crate::core_crypto::commons::plan::PlanMap<usize, PlanWrapper>;

pub(crate) static PLANS: OnceLock<PlanMap> = OnceLock::new();
fn plans() -> &'static PlanMap {
PLANS.get_or_init(|| RwLock::new(HashMap::new()))
Expand All @@ -58,34 +59,10 @@ impl Fft128 {
let global_plans = plans();

let n = size.0;
let get_plan = || {
let plans = global_plans.read().unwrap();
let plan = plans.get(&n).cloned();
drop(plans);

plan.map(|p| {
p.get_or_init(|| Arc::new(PlanWrapper(Plan::new(n / 2))))
.clone()
})
};

get_plan().map_or_else(
|| {
// If we don't find a plan for the given size, we insert a new OnceLock,
// drop the write lock on the map and then let get_plan() initialize the OnceLock
// (without holding the write lock on the map).
let mut plans = global_plans.write().unwrap();
if let Entry::Vacant(v) = plans.entry(n) {
v.insert(Arc::new(OnceLock::new()));
}
drop(plans);

Self {
plan: get_plan().unwrap(),
}
},
|plan| Self { plan },
)
let plan = new_from_plan_map(global_plans, n, |n| PlanWrapper(Plan::new(n / 2)));

Self { plan }
}
}

Expand Down
78 changes: 29 additions & 49 deletions tfhe/src/core_crypto/fft_impl/fft64/math/fft/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::core_crypto::commons::math::torus::UnsignedTorus;
use crate::core_crypto::commons::numeric::CastInto;
pub use crate::core_crypto::commons::parameters::PolynomialSize;
use crate::core_crypto::commons::parameters::{FourierPolynomialSize, PolynomialCount};
use crate::core_crypto::commons::plan::new_from_plan_map;
use crate::core_crypto::commons::traits::{Container, ContainerMut, IntoContainerOwned};
use crate::core_crypto::commons::utils::izip_eq;
use crate::core_crypto::entities::*;
Expand Down Expand Up @@ -101,7 +102,8 @@ impl Fft {
}
}

type PlanMap = RwLock<HashMap<usize, Arc<OnceLock<Arc<(Twisties, Plan)>>>>>;
type PlanMap = crate::core_crypto::commons::plan::PlanMap<usize, (Twisties, Plan)>;

pub(crate) static PLANS: OnceLock<PlanMap> = OnceLock::new();
fn plans() -> &'static PlanMap {
PLANS.get_or_init(|| RwLock::new(HashMap::new()))
Expand All @@ -118,9 +120,9 @@ pub fn setup_custom_fft_plan(plan: Plan) {
let mut write = global_plans.write().unwrap();

match write.entry(n.0) {
Entry::Occupied(mut occupied_entry) => occupied_entry.get_mut().set(plan).unwrap(),
Entry::Occupied(mut occupied_entry) => *occupied_entry.get_mut() = plan,
Entry::Vacant(vacant_entry) => {
vacant_entry.insert(Arc::new(OnceLock::from(plan)));
vacant_entry.insert(plan);
}
}
}
Expand Down Expand Up @@ -171,55 +173,33 @@ impl Fft {
let global_plans = plans();

let n = size.0;
let get_plan = || {
let plans = global_plans.read().unwrap();
let plan = plans.get(&n).cloned();
drop(plans);

plan.map(|p| {
p.get_or_init(|| {
#[cfg(not(feature = "experimental-force_fft_algo_dif4"))]
{
Arc::new((
Twisties::new(n / 2),
Plan::new(n / 2, Method::Measure(Duration::from_millis(10))),
))
}
#[cfg(feature = "experimental-force_fft_algo_dif4")]
{
Arc::new((
Twisties::new(n / 2),
Plan::new(
n / 2,
Method::UserProvided {
base_algo: tfhe_fft::ordered::FftAlgo::Dif4,
base_n: n / 2,
},
),
))
}
})
.clone()
})

let new = |n| {
#[cfg(not(feature = "experimental-force_fft_algo_dif4"))]
{
(
Twisties::new(n / 2),
Plan::new(n / 2, Method::Measure(Duration::from_millis(10))),
)
}
#[cfg(feature = "experimental-force_fft_algo_dif4")]
{
(
Twisties::new(n / 2),
Plan::new(
n / 2,
Method::UserProvided {
base_algo: tfhe_fft::ordered::FftAlgo::Dif4,
base_n: n / 2,
},
),
)
}
};

get_plan().map_or_else(
|| {
// If we don't find a plan for the given size, we insert a new OnceLock,
// drop the write lock on the map and then let get_plan() initialize the OnceLock
// (without holding the write lock on the map).
let mut plans = global_plans.write().unwrap();
if let Entry::Vacant(v) = plans.entry(n) {
v.insert(Arc::new(OnceLock::new()));
}
drop(plans);
let plan = new_from_plan_map(global_plans, n, new);

Self {
plan: get_plan().unwrap(),
}
},
|plan| Self { plan },
)
Self { plan }
}
}

Expand Down
Loading