Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inverse cpu and rust wrappers #747

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion docs/versioned_docs/version-2.8.0/icicle/primitives/msm.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ The MSM supports batch mode - running multiple MSMs in parallel. It's always bet
struct MSMConfig {
device_context::DeviceContext ctx; /**< Details related to the device such as its id and stream id. */
int points_size; /**< Number of points in the MSM. If a batch of MSMs needs to be computed, this should be
* a number of different points. So, if each MSM re-uses the same set of points, this
* a number of different points. So, if each MSM reuses the same set of points, this
* variable is set equal to the MSM size. And if every MSM uses a distinct set of
* points, it should be set to the product of MSM size and [batch_size](@ref
* batch_size). Default value: 0 (meaning it's equal to the MSM size). */
Expand Down
2 changes: 1 addition & 1 deletion examples/c++/polynomial-multiplication/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void incremental_values(scalar_t* res, uint32_t count)
}
}

// calcaulting polynomial multiplication A*B via NTT,pointwise-multiplication and INTT
// calculating polynomial multiplication A*B via NTT,pointwise-multiplication and INTT
// (1) allocate A,B on HOST. Randomize first half, zero second half
// (2) allocate A,B,Res on device
// (3) calc NTT for A and for B from host to device
Expand Down
19 changes: 19 additions & 0 deletions icicle/backend/cpu/src/field/cpu_vec_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum VecOperation {
VECTOR_SUB,
VECTOR_MUL,
VECTOR_DIV,
VECTOR_INV,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can break code compatibility? should add as last and a TODO to re-order on next major

CONVERT_TO_MONTGOMERY,
CONVERT_FROM_MONTGOMERY,
VECTOR_SUM,
Expand Down Expand Up @@ -206,6 +207,13 @@ class VectorOpTask : public TaskBase
m_output[i] = m_op_a[i] * U::inverse(m_op_b[i]);
}
}
// Single worker functionality to execute vector inv (^-1)
void vector_inv()
{
for (uint64_t i = 0; i < m_nof_operations; ++i) {
m_output[i] = T::inverse(m_op_a[i]);
}
}
// Single worker functionality to execute conversion from barret to montgomery
void convert_to_montgomery()
{
Expand Down Expand Up @@ -338,6 +346,7 @@ class VectorOpTask : public TaskBase
&VectorOpTask::vector_sub, // VECTOR_SUB,
&VectorOpTask::vector_mul, // VECTOR_MUL,
&VectorOpTask::vector_div, // VECTOR_DIV,
&VectorOpTask::vector_inv, // VECTOR_INV,
&VectorOpTask::convert_to_montgomery, // CONVERT_TO_MONTGOMERY,
&VectorOpTask::convert_from_montgomery, // CONVERT_FROM_MONTGOMERY,
&VectorOpTask::vector_sum, // VECTOR_SUM
Expand Down Expand Up @@ -476,6 +485,15 @@ eIcicleError cpu_vector_div(

REGISTER_VECTOR_DIV_BACKEND("CPU", cpu_vector_div<scalar_t>);

/*********************************** INV ***********************************/
template <typename T>
eIcicleError cpu_vector_inv(const Device& device, const T* vec_a, uint64_t size, const VecOpsConfig& config, T* output)
{
return cpu_2vectors_op(VecOperation::VECTOR_INV, vec_a, vec_a, size, config, output);
}

REGISTER_VECTOR_INV_BACKEND("CPU", cpu_vector_inv<scalar_t>);

/*********************************** CONVERT MONTGOMERY ***********************************/
template <typename T>
eIcicleError cpu_convert_montgomery(
Expand Down Expand Up @@ -999,6 +1017,7 @@ REGISTER_VECTOR_SUB_EXT_FIELD_BACKEND("CPU", cpu_vector_sub<extension_t>);
REGISTER_VECTOR_MUL_EXT_FIELD_BACKEND("CPU", (cpu_vector_mul<extension_t, extension_t>));
REGISTER_VECTOR_MIXED_MUL_BACKEND("CPU", (cpu_vector_mul<extension_t, scalar_t>));
REGISTER_VECTOR_DIV_EXT_FIELD_BACKEND("CPU", cpu_vector_div<extension_t>);
REGISTER_VECTOR_INV_EXT_FIELD_BACKEND("CPU", cpu_vector_inv<extension_t>);
REGISTER_CONVERT_MONTGOMERY_EXT_FIELD_BACKEND("CPU", cpu_convert_montgomery<extension_t>);
REGISTER_VECTOR_SUM_EXT_FIELD_BACKEND("CPU", cpu_vector_sum<extension_t>);
REGISTER_VECTOR_PRODUCT_EXT_FIELD_BACKEND("CPU", cpu_vector_product<extension_t>);
Expand Down
20 changes: 20 additions & 0 deletions icicle/include/icicle/backend/vec_ops_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ namespace icicle {
}(); \
}

void register_vector_inv(const std::string& deviceType, VectorReduceOpImpl impl);

#define REGISTER_VECTOR_INV_BACKEND(DEVICE_TYPE, FUNC) \
namespace { \
static bool UNIQUE(_reg_vec_inv) = []() -> bool { \
register_vector_inv(DEVICE_TYPE, FUNC); \
return true; \
}(); \
}

void register_vector_sub(const std::string& deviceType, scalarVectorOpImpl impl);
#define REGISTER_VECTOR_SUB_BACKEND(DEVICE_TYPE, FUNC) \
namespace { \
Expand Down Expand Up @@ -303,6 +313,16 @@ namespace icicle {
}(); \
}

void register_extension_vector_inv(const std::string& deviceType, extFieldVectorReduceOpImpl impl);

#define REGISTER_VECTOR_INV_EXT_FIELD_BACKEND(DEVICE_TYPE, FUNC) \
namespace { \
static bool UNIQUE(_reg_vec_inv_ext_field) = []() -> bool { \
register_extension_vector_inv(DEVICE_TYPE, FUNC); \
return true; \
}(); \
}

void register_extension_vector_sub(const std::string& deviceType, extFieldVectorOpImpl impl);
#define REGISTER_VECTOR_SUB_EXT_FIELD_BACKEND(DEVICE_TYPE, FUNC) \
namespace { \
Expand Down
18 changes: 18 additions & 0 deletions icicle/include/icicle/vec_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,24 @@ namespace icicle {
template <typename T>
eIcicleError vector_div(const T* vec_a, const T* vec_b, uint64_t size, const VecOpsConfig& config, T* output);

/**
* @brief Invert vector `a` element-wise.
*
* @tparam T Type of the elements in the vectors.
* @param vec_a Pointer to the first input vector(s).
* - If `config.batch_size > 1`, this should be a concatenated array of vectors.
* - The layout depends on `config.columns_batch`:
* - If `false`, vectors are stored contiguously in memory.
* - If `true`, vectors are stored as columns in a 2D array.
* @param size Number of elements in each vector.
* @param config Configuration for the operation.
* @param output Pointer to the output vector(s) where the results will be stored.
* The output array should have the same storage layout as the input vectors.
* @return eIcicleError Error code indicating success or failure.
*/
template <typename T>
eIcicleError vector_inv(const T* vec_a, uint64_t size, const VecOpsConfig& config, T* output);

/**
* @brief Converts elements to and from Montgomery form.
*
Expand Down
31 changes: 31 additions & 0 deletions icicle/src/vec_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,37 @@ namespace icicle {
}
#endif // EXT_FIELD

/*********************************** INV ***********************************/
ICICLE_DISPATCHER_INST(VectorInvDispatcher, vector_inv, VectorReduceOpImpl);

extern "C" eIcicleError
CONCAT_EXPAND(FIELD, vector_inv)(const scalar_t* vec_a, uint64_t size, const VecOpsConfig* config, scalar_t* output)
{
return VectorInvDispatcher::execute(vec_a, size, *config, output);
}

template <>
eIcicleError vector_inv(const scalar_t* vec_a, uint64_t size, const VecOpsConfig& config, scalar_t* output)
{
return CONCAT_EXPAND(FIELD, vector_inv)(vec_a, size, &config, output);
}

#ifdef EXT_FIELD
ICICLE_DISPATCHER_INST(VectorInvExtFieldDispatcher, extension_vector_inv, extFieldVectorReduceOpImpl);

extern "C" eIcicleError CONCAT_EXPAND(FIELD, extension_vector_inv)(
const extension_t* vec_a, uint64_t size, const VecOpsConfig* config, extension_t* output)
{
return VectorInvExtFieldDispatcher::execute(vec_a, size, *config, output);
}

template <>
eIcicleError vector_inv(const extension_t* vec_a, uint64_t size, const VecOpsConfig& config, extension_t* output)
{
return CONCAT_EXPAND(FIELD, extension_vector_inv)(vec_a, size, &config, output);
}
#endif // EXT_FIELD

/*********************************** (Scalar + Vector) ELEMENT WISE ***********************************/
ICICLE_DISPATCHER_INST(ScalarAddDispatcher, scalar_add_vec, scalarVectorOpImpl);

Expand Down
2 changes: 1 addition & 1 deletion wrappers/rust/icicle-core/src/msm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub trait MSM<C: Curve> {
/// * `scalars` - scalar values `s1, s2, ..., sn`.
///
/// * `bases` - bases `P1, P2, ..., Pn`. The number of bases can be smaller than the number of scalars
/// in the case of batch MSM. In this case bases are re-used periodically. Alternatively, there can be more bases
/// in the case of batch MSM. In this case bases are reused periodically. Alternatively, there can be more bases
/// than scalars if precomputation has been performed, you need to set `cfg.precompute_factor` in that case.
///
/// * `cfg` - config used to specify extra arguments of the MSM.
Expand Down
43 changes: 43 additions & 0 deletions wrappers/rust/icicle-core/src/vec_ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ pub trait VecOps<F> {
cfg: &VecOpsConfig,
) -> Result<(), eIcicleError>;

fn inv(
a: &(impl HostOrDeviceSlice<F> + ?Sized),
result: &mut (impl HostOrDeviceSlice<F> + ?Sized),
cfg: &VecOpsConfig,
) -> Result<(), eIcicleError>;

fn sum(
a: &(impl HostOrDeviceSlice<F> + ?Sized),
result: &mut (impl HostOrDeviceSlice<F> + ?Sized),
Expand Down Expand Up @@ -371,6 +377,19 @@ where
<<F as FieldImpl>::Config as VecOps<F>>::div(a, b, result, &cfg)
}

pub fn inv_scalars<F>(
a: &(impl HostOrDeviceSlice<F> + ?Sized),
result: &mut (impl HostOrDeviceSlice<F> + ?Sized),
cfg: &VecOpsConfig,
) -> Result<(), eIcicleError>
where
F: FieldImpl,
<F as FieldImpl>::Config: VecOps<F>,
{
let cfg = check_vec_ops_args(a, a, result, cfg);
<<F as FieldImpl>::Config as VecOps<F>>::inv(a, result, &cfg)
}

pub fn sum_scalars<F>(
a: &(impl HostOrDeviceSlice<F> + ?Sized),
result: &mut (impl HostOrDeviceSlice<F> + ?Sized),
Expand Down Expand Up @@ -555,6 +574,14 @@ macro_rules! impl_vec_ops_field {
result: *mut $field,
) -> eIcicleError;

#[link_name = concat!($field_prefix, "_vector_inv")]
pub(crate) fn vector_inv_ffi(
a: *const $field,
size: u32,
cfg: *const VecOpsConfig,
result: *mut $field,
) -> eIcicleError;

#[link_name = concat!($field_prefix, "_vector_sum")]
pub(crate) fn vector_sum_ffi(
a: *const $field,
Expand Down Expand Up @@ -717,6 +744,22 @@ macro_rules! impl_vec_ops_field {
}
}

fn inv(
a: &(impl HostOrDeviceSlice<$field> + ?Sized),
result: &mut (impl HostOrDeviceSlice<$field> + ?Sized),
cfg: &VecOpsConfig,
) -> Result<(), eIcicleError> {
unsafe {
$field_prefix_ident::vector_inv_ffi(
a.as_ptr(),
a.len() as u32,
cfg as *const VecOpsConfig,
result.as_mut_ptr(),
)
.wrap()
}
}

fn sum(
a: &(impl HostOrDeviceSlice<$field> + ?Sized),
result: &mut (impl HostOrDeviceSlice<$field> + ?Sized),
Expand Down
47 changes: 39 additions & 8 deletions wrappers/rust/icicle-core/src/vec_ops/tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(unused_imports)]
use crate::traits::GenerateRandom;
use crate::vec_ops::{
accumulate_scalars, add_scalars, bit_reverse, bit_reverse_inplace, div_scalars, mixed_mul_scalars, mul_scalars,
accumulate_scalars, add_scalars, bit_reverse, bit_reverse_inplace, div_scalars, inv_scalars, mixed_mul_scalars, mul_scalars,
product_scalars, scalar_add, scalar_mul, scalar_sub, slice, sub_scalars, sum_scalars, transpose_matrix, FieldImpl,
MixedVecOps, VecOps, VecOpsConfig,
};
Expand Down Expand Up @@ -42,6 +42,7 @@ where
check_vec_ops_scalars_sub::<F>(test_size);
check_vec_ops_scalars_mul::<F>(test_size);
check_vec_ops_scalars_div::<F>(test_size);
check_vec_ops_scalars_inv::<F>(test_size);
check_vec_ops_scalars_sum::<F>(test_size);
check_vec_ops_scalars_product::<F>(test_size);
check_vec_ops_scalars_add_scalar::<F>(test_size);
Expand Down Expand Up @@ -161,11 +162,41 @@ where
assert_eq!(result_main.as_slice(), result_ref.as_slice());
}

pub fn check_vec_ops_scalars_inv<F: FieldImpl>(test_size: usize)
where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let cfg = VecOpsConfig::default();

let a = F::Config::generate_random(test_size);
let mut inv = vec![F::zero(); test_size];
let mut result_main = vec![F::zero(); test_size];
let mut result_ref = vec![F::one(); test_size];
let mut result = vec![F::one(); test_size];

let a = HostSlice::from_slice(&a);
let inv = HostSlice::from_mut_slice(&mut inv);
let result_main = HostSlice::from_mut_slice(&mut result_main);
let result_ref = HostSlice::from_mut_slice(&mut result_ref);
let result = HostSlice::from_mut_slice(&mut result);

test_utilities::test_set_main_device();
inv_scalars(a, inv, &cfg).unwrap();
mul_scalars(a, inv, result_main, &cfg).unwrap();

test_utilities::test_set_ref_device();
inv_scalars(a, inv, &cfg).unwrap();
mul_scalars(a, inv, result_ref, &cfg).unwrap();

assert_eq!(result_main.as_slice(), result.as_slice());
assert_eq!(result_ref.as_slice(), result.as_slice());
}

pub fn check_vec_ops_scalars_sum<F: FieldImpl>(test_size: usize)
where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let mut cfg = VecOpsConfig::default();
let cfg = VecOpsConfig::default();
let batch_size = 3;

let a_main = F::Config::generate_random(test_size * batch_size);
Expand All @@ -189,7 +220,7 @@ pub fn check_vec_ops_scalars_product<F: FieldImpl>(test_size: usize)
where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let mut cfg = VecOpsConfig::default();
let cfg = VecOpsConfig::default();
let batch_size = 3;

let a_main = F::Config::generate_random(test_size * batch_size);
Expand All @@ -214,7 +245,7 @@ where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let mut cfg = VecOpsConfig::default();
let batch_size = 3;
cfg.batch_size = 3;

let a_main = F::Config::generate_random(cfg.batch_size as usize);
let b = F::Config::generate_random(test_size * cfg.batch_size as usize);
Expand All @@ -239,7 +270,7 @@ pub fn check_vec_ops_scalars_sub_scalar<F: FieldImpl>(test_size: usize)
where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let mut cfg = VecOpsConfig::default();
let cfg = VecOpsConfig::default();
let batch_size = 3;

let a_main = F::Config::generate_random(batch_size);
Expand All @@ -265,7 +296,7 @@ pub fn check_vec_ops_scalars_mul_scalar<F: FieldImpl>(test_size: usize)
where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let mut cfg = VecOpsConfig::default();
let cfg = VecOpsConfig::default();
let batch_size = 3;

let a_main = F::Config::generate_random(batch_size);
Expand Down Expand Up @@ -315,7 +346,7 @@ pub fn check_matrix_transpose<F: FieldImpl>()
where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let mut cfg = VecOpsConfig::default();
let cfg = VecOpsConfig::default();
let batch_size = 3;

let (r, c): (u32, u32) = (1u32 << 10, 1u32 << 4);
Expand Down Expand Up @@ -352,7 +383,7 @@ pub fn check_slice<F: FieldImpl>()
where
<F as FieldImpl>::Config: VecOps<F> + GenerateRandom<F>,
{
let mut cfg = VecOpsConfig::default();
let cfg = VecOpsConfig::default();
let batch_size = 3;

let size_in: u64 = 1 << 10;
Expand Down
Loading