Skip to main content
Version: 1.10.1

Vector Operations API

Our vector operations API which is part of icicle-cuda-runtime package, includes fundamental methods for addition, subtraction, and multiplication of vectors, with support for both host and device memory.

Supported curves​

Vector operations are supported on the following curves:

bls12-377, bls12-381, bn-254, bw6-761, grumpkin

Examples​

Addition of Scalars​

use icicle_bn254::curve::{ScalarCfg, ScalarField};
use icicle_core::vec_ops::{add_scalars};

let test_size = 1 << 18;

let a: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(F::Config::generate_random(test_size));
let b: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(F::Config::generate_random(test_size));
let mut result: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(vec![F::zero(); test_size]);

let cfg = VecOpsConfig::default();
add_scalars(&a, &b, &mut result, &cfg).unwrap();

Subtraction of Scalars​

use icicle_bn254::curve::{ScalarCfg, ScalarField};
use icicle_core::vec_ops::{sub_scalars};

let test_size = 1 << 18;

let a: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(F::Config::generate_random(test_size));
let b: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(F::Config::generate_random(test_size));
let mut result: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(vec![F::zero(); test_size]);

let cfg = VecOpsConfig::default();
sub_scalars(&a, &b, &mut result, &cfg).unwrap();

Multiplication of Scalars​

use icicle_bn254::curve::{ScalarCfg, ScalarField};
use icicle_core::vec_ops::{mul_scalars};

let test_size = 1 << 18;

let a: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(F::Config::generate_random(test_size));
let ones: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(vec![F::one(); test_size]);
let mut result: HostOrDeviceSlice<'_, ScalarField> = HostOrDeviceSlice::on_host(vec![F::zero(); test_size]);

let cfg = VecOpsConfig::default();
mul_scalars(&a, &ones, &mut result, &cfg).unwrap();

Vector Operations Configuration​

The VecOpsConfig struct encapsulates the settings for vector operations, including device context and operation modes.

VecOpsConfig​

Defines configuration parameters for vector operations.

pub struct VecOpsConfig<'a> {
pub ctx: DeviceContext<'a>,
is_a_on_device: bool,
is_b_on_device: bool,
is_result_on_device: bool,
is_result_montgomery_form: bool,
pub is_async: bool,
}

Fields​

  • ctx: DeviceContext<'a>: Specifies the device context for the operation, including the device ID and memory pool.
  • is_a_on_device: Indicates if the first operand vector resides in device memory.
  • is_b_on_device: Indicates if the second operand vector resides in device memory.
  • is_result_on_device: Specifies if the result vector should be stored in device memory.
  • is_result_montgomery_form: Determines if the result should be in Montgomery form.
  • is_async: Enables asynchronous operation. If true, operations are non-blocking; otherwise, they block the current thread.

Default Configuration​

VecOpsConfig can be initialized with default settings tailored for a specific device:

let cfg = VecOpsConfig::default();

These are the default settings.

impl<'a> Default for VecOpsConfig<'a> {
fn default() -> Self {
Self::default_for_device(DEFAULT_DEVICE_ID)
}
}

impl<'a> VecOpsConfig<'a> {
pub fn default_for_device(device_id: usize) -> Self {
VecOpsConfig {
ctx: DeviceContext::default_for_device(device_id),
is_a_on_device: false,
is_b_on_device: false,
is_result_on_device: false,
is_result_montgomery_form: false,
is_async: false,
}
}
}

Vector Operations​

Vector operations are implemented through the VecOps trait, these traits are implemented for all supported curves providing methods for addition, subtraction, and multiplication of vectors.

VecOps Trait​

pub trait VecOps<F> {
fn add(
a: &HostOrDeviceSlice<F>,
b: &HostOrDeviceSlice<F>,
result: &mut HostOrDeviceSlice<F>,
cfg: &VecOpsConfig,
) -> IcicleResult<()>;

fn sub(
a: &HostOrDeviceSlice<F>,
b: &HostOrDeviceSlice<F>,
result: &mut HostOrDeviceSlice<F>,
cfg: &VecOpsConfig,
) -> IcicleResult<()>;

fn mul(
a: &HostOrDeviceSlice<F>,
b: &HostOrDeviceSlice<F>,
result: &mut HostOrDeviceSlice<F>,
cfg: &VecOpsConfig,
) -> IcicleResult<()>;
}

Methods​

All operations are element-wise operations, and the results placed into the result param. These operations are not in place.

  • add: Computes the element-wise sum of two vectors.
  • sub: Computes the element-wise difference between two vectors.
  • mul: Performs element-wise multiplication of two vectors.