diff --git a/halo2_proofs/Cargo.toml b/halo2_proofs/Cargo.toml index 7060849b4d..6b6bb7eb99 100644 --- a/halo2_proofs/Cargo.toml +++ b/halo2_proofs/Cargo.toml @@ -63,7 +63,9 @@ env_logger = "0.10.0" rustc-hash = "2.0.0" lazy_static = "1.4.0" # GPU Icicle integration -icicle = { git = "https://github.com/ingonyama-zk/icicle.git", branch = "rust/large-bucket-factor-msm", optional = true } +icicle-core = { git = "https://github.com/ingonyama-zk/icicle", branch="ezkl-icicle2", package="icicle-core", optional = true } +icicle-bn254 = { git = "https://github.com/ingonyama-zk/icicle", branch="ezkl-icicle2", package="icicle-bn254", optional = true } +icicle-cuda-runtime = { git = "https://github.com/ingonyama-zk/icicle", branch="ezkl-icicle2", package="icicle-cuda-runtime", optional = true } rustacuda = { version = "0.1", optional = true } serde_derive = { version = "1", optional = true} bincode = { version = "1.3.3", default_features = false } @@ -107,7 +109,7 @@ sanity-checks = [] batch = ["rand_core/getrandom"] circuit-params = [] counter = [] -icicle_gpu = ["icicle", "rustacuda"] +icicle_gpu = ["icicle-cuda-runtime", "icicle-core", "icicle-bn254"] mv-lookup = [] cost-estimator = ["serde_derive"] derive_serde = ["halo2curves/derive_serde"] diff --git a/halo2_proofs/benches/arithmetic.rs b/halo2_proofs/benches/arithmetic.rs index 19f94f2807..9498a52164 100644 --- a/halo2_proofs/benches/arithmetic.rs +++ b/halo2_proofs/benches/arithmetic.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate criterion; -use crate::arithmetic::best_multiexp_cpu; +use crate::arithmetic::best_multiexp; use crate::halo2curves::pasta::{EqAffine, Fp}; use group::ff::Field; use halo2_proofs::*; @@ -27,7 +27,7 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function("double-and-add", |b| { b.iter(|| { for (g_lo, g_hi) in g_lo.iter().zip(g_hi.iter()) { - best_multiexp_cpu(&[black_box(coeff_1), black_box(coeff_2)], &[*g_lo, *g_hi]); + best_multiexp(&[black_box(coeff_1), black_box(coeff_2)], &[*g_lo, *g_hi]); } }) }); diff --git a/halo2_proofs/src/arithmetic.rs b/halo2_proofs/src/arithmetic.rs index 35ad44c607..b97595f1a6 100644 --- a/halo2_proofs/src/arithmetic.rs +++ b/halo2_proofs/src/arithmetic.rs @@ -3,6 +3,8 @@ #[cfg(feature = "icicle_gpu")] use super::icicle; +#[cfg(feature = "icicle_gpu")] +use std::env; use super::multicore; pub use ff::Field; use group::{ @@ -10,8 +12,6 @@ use group::{ prime::PrimeCurveAffine, Curve, GroupOpsOwned, ScalarMulOwned, }; -#[cfg(feature = "icicle_gpu")] -use rustacuda::prelude::DeviceBuffer; use halo2curves::msm::msm_best; pub use halo2curves::{CurveAffine, CurveExt}; @@ -31,6 +31,24 @@ where { } +/// Best MSM +pub fn best_multiexp( + coeffs: &[C::Scalar], bases: &[C] +) -> C::Curve { + #[cfg(feature = "icicle_gpu")] + if env::var("ENABLE_ICICLE_GPU").is_ok() + && !icicle::should_use_cpu_msm(coeffs.len()) + && icicle::is_gpu_supported_field(&coeffs[0]) + { + best_multiexp_gpu(coeffs, bases) + } else { + best_multiexp_cpu(coeffs, bases) + } + + #[cfg(not(feature = "icicle_gpu"))] + best_multiexp_cpu(coeffs, bases) +} + // [JPW] Keep this adapter to halo2curves to minimize code changes. /// Performs a multi-exponentiation operation. /// @@ -43,15 +61,12 @@ pub fn best_multiexp_cpu(coeffs: &[C::Scalar], bases: &[C]) -> C #[cfg(feature = "icicle_gpu")] /// Performs a multi-exponentiation operation on GPU using Icicle library -pub fn best_multiexp_gpu(coeffs: &[C::Scalar], is_lagrange: bool) -> C::Curve { - let scalars_ptr: DeviceBuffer<::icicle::curves::bn254::ScalarField_BN254> = - icicle::copy_scalars_to_device::(coeffs); - - return icicle::multiexp_on_device::(scalars_ptr, is_lagrange); +pub fn best_multiexp_gpu(coeffs: &[C::Scalar], g: &[C]) -> C::Curve { + icicle::multiexp_on_device::(coeffs, g) } /// Dispatcher -pub fn best_fft>( +pub fn best_fft_cpu>( a: &mut [G], omega: Scalar, log_n: u32, @@ -61,6 +76,40 @@ pub fn best_fft>( fft::fft(a, omega, log_n, data, inverse); } +/// Best FFT +pub fn best_fft + ff::PrimeField>( + scalars: &mut [G], + omega: Scalar, + log_n: u32, + data: &FFTData, + inverse: bool, +) { + #[cfg(feature = "icicle_gpu")] + if env::var("ENABLE_ICICLE_GPU").is_ok() + && !icicle::should_use_cpu_fft(scalars.len()) + && icicle::is_gpu_supported_field(&omega) + { + best_fft_gpu(scalars, omega, log_n, inverse); + } else { + best_fft_cpu(scalars, omega, log_n, data, inverse); + } + + #[cfg(not(feature = "icicle_gpu"))] + best_fft_cpu(scalars, omega, log_n, data, inverse); +} + +/// Performs a NTT operation on GPU using Icicle library +#[cfg(feature = "icicle_gpu")] +pub fn best_fft_gpu + ff::PrimeField>( + a: &mut [G], + omega: Scalar, + log_n: u32, + inverse: bool, +) { + println!("icicle_fft"); + icicle::fft_on_device::(a, omega, log_n, inverse); +} + /// Convert coefficient bases group elements to lagrange basis by inverse FFT. pub fn g_to_lagrange(g_projective: Vec, k: u32) -> Vec { let n_inv = C::Scalar::TWO_INV.pow_vartime([k as u64, 0, 0, 0]); @@ -74,7 +123,7 @@ pub fn g_to_lagrange(g_projective: Vec, k: u32) - let n = g_lagrange_projective.len(); let fft_data = FFTData::new(n, omega, omega_inv); - best_fft(&mut g_lagrange_projective, omega_inv, k, &fft_data, true); + best_fft_cpu(&mut g_lagrange_projective, omega_inv, k, &fft_data, true); parallelize(&mut g_lagrange_projective, |g, _| { for g in g.iter_mut() { *g *= n_inv; diff --git a/halo2_proofs/src/icicle.rs b/halo2_proofs/src/icicle.rs index cd50af6582..31bb34f680 100644 --- a/halo2_proofs/src/icicle.rs +++ b/halo2_proofs/src/icicle.rs @@ -1,48 +1,34 @@ use group::ff::PrimeField; -use icicle::{ - curves::bn254::{Point_BN254, ScalarField_BN254}, - test_bn254::commit_bn254, -}; -use std::sync::{Arc, Once}; - -pub use icicle::curves::bn254::PointAffineNoInfinity_BN254; -use rustacuda::memory::CopyDestination; -use rustacuda::prelude::*; - +use icicle_bn254::curve::{CurveCfg, G1Projective, ScalarField}; +use halo2curves::bn256::Fr as Bn256Fr; +use icicle_cuda_runtime::memory::{DeviceVec, HostSlice}; +use crate::arithmetic::FftGroup; +use std::any::{TypeId, Any}; pub use halo2curves::CurveAffine; +use icicle_core::{ + curve::Affine, + msm, + ntt::{initialize_domain, ntt_inplace, NTTConfig, NTTDir}, +}; +use maybe_rayon::iter::IntoParallelRefIterator; +use maybe_rayon::iter::ParallelIterator; use std::{env, mem}; -static mut GPU_CONTEXT: Option = None; -static mut GPU_G: Option> = None; -static mut GPU_G_LAGRANGE: Option> = None; -static GPU_INIT: Once = Once::new(); - pub fn should_use_cpu_msm(size: usize) -> bool { size <= (1 - << u8::from_str_radix(&env::var("ICICLE_SMALL_K").unwrap_or("8".to_string()), 10).unwrap()) + << u8::from_str_radix(&env::var("ICICLE_SMALL_K").unwrap_or("2".to_string()), 10).unwrap()) } -pub fn init_gpu(g: &[C], g_lagrange: &[C]) { - unsafe { - GPU_INIT.call_once(|| { - GPU_CONTEXT = Some(rustacuda::quick_init().unwrap()); - GPU_G = Some(copy_points_to_device(g)); - GPU_G_LAGRANGE = Some(copy_points_to_device(g_lagrange)); - }); - } +pub fn should_use_cpu_fft(size: usize) -> bool { + size <= (1 + << u8::from_str_radix(&env::var("ICICLE_SMALL_K_FFT").unwrap_or("2".to_string()), 10).unwrap()) } -fn u32_from_u8(u8_arr: &[u8; 32]) -> [u32; 8] { - let mut t = [0u32; 8]; - for i in 0..8 { - t[i] = u32::from_le_bytes([ - u8_arr[4 * i], - u8_arr[4 * i + 1], - u8_arr[4 * i + 2], - u8_arr[4 * i + 3], - ]); +pub fn is_gpu_supported_field(_sample_element: &G) -> bool { + match TypeId::of::() { + id if id == TypeId::of::() => true, + _ => false, } - return t; } fn repr_from_u32(u32_arr: &[u32; 8]) -> ::Base { @@ -51,96 +37,87 @@ fn repr_from_u32(u32_arr: &[u32; 8]) -> ::Base return PrimeField::from_repr(t[0]).unwrap(); } -fn is_infinity_point(point: Point_BN254) -> bool { - let inf_point = Point_BN254::infinity(); - point.z.s.eq(&inf_point.z.s) +fn icicle_scalars_from_c_scalars(coeffs: &[G]) -> Vec { + coeffs.par_iter().map(|coef| { + let repr: [u32; 8] = unsafe { mem::transmute_copy(&coef.to_repr()) }; + ScalarField::from(repr) + }).collect() } -fn icicle_scalars_from_c(coeffs: &[C::Scalar]) -> Vec { - let _coeffs = [Arc::new( - coeffs.iter().map(|x| x.to_repr()).collect::>(), - )]; - - let _coeffs: &Arc> = unsafe { mem::transmute(&_coeffs) }; - _coeffs - .iter() - .map(|x| ScalarField_BN254::from_limbs(x)) - .collect::>() +fn c_scalars_from_icicle_scalars(scalars: &[ScalarField]) -> Vec { + scalars.par_iter().map(|scalar| { + let repr: G::Repr = unsafe { mem::transmute_copy(scalar) }; + G::from_repr(repr).unwrap() + }).collect() } -pub fn copy_scalars_to_device( - coeffs: &[C::Scalar], -) -> DeviceBuffer { - let scalars = icicle_scalars_from_c::(coeffs); - - DeviceBuffer::from_slice(scalars.as_slice()).unwrap() -} +fn icicle_points_from_c(bases: &[C]) -> Vec> { + bases.par_iter().map(|p| { + let coordinates = p.coordinates().unwrap(); + let x_repr: [u32; 8] = unsafe { mem::transmute_copy(&coordinates.x().to_repr()) }; + let y_repr: [u32; 8] = unsafe { mem::transmute_copy(&coordinates.y().to_repr()) }; -fn icicle_points_from_c(bases: &[C]) -> Vec { - let _bases = [Arc::new( - bases - .iter() - .map(|p| { - let coordinates = p.coordinates().unwrap(); - [coordinates.x().to_repr(), coordinates.y().to_repr()] - }) - .collect::>(), - )]; - - let _bases: &Arc> = unsafe { mem::transmute(&_bases) }; - _bases - .iter() - .map(|x| { - let tx = u32_from_u8(&x[0]); - let ty = u32_from_u8(&x[1]); - PointAffineNoInfinity_BN254::from_limbs(&tx, &ty) - }) - .collect::>() + Affine::::from_limbs(x_repr, y_repr) + }).collect() } -pub fn copy_points_to_device( - bases: &[C], -) -> DeviceBuffer { - let points = icicle_points_from_c(bases); +fn c_from_icicle_point(point: &G1Projective) -> C::Curve { + let (x, y) = { + let affine: Affine = Affine::::from(*point); - DeviceBuffer::from_slice(points.as_slice()).unwrap() -} - -fn c_from_icicle_point(commit_res: Point_BN254) -> C::Curve { - let (x, y) = if is_infinity_point(commit_res) { ( - repr_from_u32::(&[0u32; 8]), - repr_from_u32::(&[0u32; 8]), - ) - } else { - let affine_res_from_cuda = commit_res.to_affine(); - ( - repr_from_u32::(&affine_res_from_cuda.x.s), - repr_from_u32::(&affine_res_from_cuda.y.s), + repr_from_u32::(&affine.x.into()), + repr_from_u32::(&affine.y.into()), ) }; - let affine = C::from_xy(x, y).unwrap(); - return affine.to_curve(); + let affine = C::from_xy(x, y); + + return affine.unwrap().to_curve(); } -pub fn multiexp_on_device( - mut coeffs: DeviceBuffer, - is_lagrange: bool, -) -> C::Curve { - let base_ptr: &mut DeviceBuffer; - unsafe { - if is_lagrange { - base_ptr = GPU_G_LAGRANGE.as_mut().unwrap(); - } else { - base_ptr = GPU_G.as_mut().unwrap(); - }; - } +pub fn multiexp_on_device(coeffs: &[C::Scalar], bases: &[C]) -> C::Curve { + let binding = icicle_scalars_from_c_scalars::(coeffs); + let coeffs = HostSlice::from_slice(&binding[..]); + let binding = icicle_points_from_c(bases); + let bases = HostSlice::from_slice(&binding[..]); + + let mut msm_results = DeviceVec::::cuda_malloc(1).unwrap(); + let cfg = msm::MSMConfig::default(); - let d_commit_result = commit_bn254(base_ptr, &mut coeffs, 10); + msm::msm(coeffs, bases, &cfg, &mut msm_results[..]).unwrap(); - let mut h_commit_result = Point_BN254::zero(); - d_commit_result.copy_to(&mut h_commit_result).unwrap(); + let mut msm_host_result = vec![G1Projective::zero(); 1]; + msm_results + .copy_to_host(HostSlice::from_mut_slice(&mut msm_host_result[..])) + .unwrap(); - c_from_icicle_point::(h_commit_result) + let msm_point = c_from_icicle_point::(&msm_host_result[0]); + + msm_point } + +pub fn fft_on_device + ff::PrimeField>( + scalars: &mut [G], + omega: Scalar, + _log_n: u32, + inverse: bool +) { + let cfg = NTTConfig::<'_, ScalarField>::default(); + let dir = if inverse { NTTDir::kInverse } else { NTTDir::kForward }; + + let omega = icicle_scalars_from_c_scalars(&[omega]); + initialize_domain(omega[0], &cfg.ctx, true).unwrap(); + + let mut icicle_scalars: Vec = icicle_scalars_from_c_scalars(scalars); + let host_scalars = HostSlice::from_mut_slice(&mut icicle_scalars); + + ntt_inplace::( + host_scalars, + dir, + &cfg, + ).unwrap(); + + let c_scalars = &c_scalars_from_icicle_scalars::(&mut host_scalars.as_slice())[..]; + scalars.copy_from_slice(&c_scalars); +} \ No newline at end of file diff --git a/halo2_proofs/src/poly/ipa/commitment.rs b/halo2_proofs/src/poly/ipa/commitment.rs index 96c98d5fbc..7be053c49c 100644 --- a/halo2_proofs/src/poly/ipa/commitment.rs +++ b/halo2_proofs/src/poly/ipa/commitment.rs @@ -3,7 +3,7 @@ //! //! [halo]: https://eprint.iacr.org/2019/1021 -use crate::arithmetic::{best_multiexp_cpu, g_to_lagrange, parallelize, CurveAffine, CurveExt}; +use crate::arithmetic::{best_multiexp, g_to_lagrange, parallelize, CurveAffine, CurveExt}; use crate::helpers::CurveRead; use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier}; use crate::poly::ipa::msm::MSMIPA; @@ -99,7 +99,7 @@ impl<'params, C: CurveAffine> Params<'params, C> for ParamsIPA { tmp_bases.extend(self.g_lagrange.iter()); tmp_bases.push(self.w); - best_multiexp_cpu::(&tmp_scalars, &tmp_bases) + best_multiexp::(&tmp_scalars, &tmp_bases) } /// Writes params to a buffer. @@ -219,7 +219,7 @@ impl<'params, C: CurveAffine> ParamsProver<'params, C> for ParamsIPA { tmp_bases.extend(self.g.iter()); tmp_bases.push(self.w); - best_multiexp_cpu::(&tmp_scalars, &tmp_bases) + best_multiexp::(&tmp_scalars, &tmp_bases) } fn get_g(&self) -> &[C] { diff --git a/halo2_proofs/src/poly/ipa/commitment/prover.rs b/halo2_proofs/src/poly/ipa/commitment/prover.rs index ab3b895fb8..b5e4633ffb 100644 --- a/halo2_proofs/src/poly/ipa/commitment/prover.rs +++ b/halo2_proofs/src/poly/ipa/commitment/prover.rs @@ -3,7 +3,7 @@ use rand_core::RngCore; use super::ParamsIPA; use crate::arithmetic::{ - best_multiexp_cpu, compute_inner_product, eval_polynomial, parallelize, CurveAffine, + best_multiexp, compute_inner_product, eval_polynomial, parallelize, CurveAffine, }; use crate::poly::commitment::ParamsProver; @@ -106,16 +106,16 @@ pub fn create_proof< // // TODO: If we modify multiexp to take "extra" bases, we could speed // this piece up a bit by combining the multiexps. - let l_j = best_multiexp_cpu(&p_prime[half..], &g_prime[0..half]); - let r_j = best_multiexp_cpu(&p_prime[0..half], &g_prime[half..]); + let l_j = best_multiexp(&p_prime[half..], &g_prime[0..half]); + let r_j = best_multiexp(&p_prime[0..half], &g_prime[half..]); let value_l_j = compute_inner_product(&p_prime[half..], &b[0..half]); let value_r_j = compute_inner_product(&p_prime[0..half], &b[half..]); let l_j_randomness = C::Scalar::random(&mut rng); let r_j_randomness = C::Scalar::random(&mut rng); let l_j = - l_j + &best_multiexp_cpu(&[value_l_j * &z, l_j_randomness], &[params.u, params.w]); + l_j + &best_multiexp(&[value_l_j * &z, l_j_randomness], &[params.u, params.w]); let r_j = - r_j + &best_multiexp_cpu(&[value_r_j * &z, r_j_randomness], &[params.u, params.w]); + r_j + &best_multiexp(&[value_r_j * &z, r_j_randomness], &[params.u, params.w]); let l_j = l_j.to_affine(); let r_j = r_j.to_affine(); diff --git a/halo2_proofs/src/poly/ipa/msm.rs b/halo2_proofs/src/poly/ipa/msm.rs index 27259703ed..a615ddce49 100644 --- a/halo2_proofs/src/poly/ipa/msm.rs +++ b/halo2_proofs/src/poly/ipa/msm.rs @@ -1,4 +1,4 @@ -use crate::arithmetic::{best_multiexp_cpu, CurveAffine}; +use crate::arithmetic::{best_multiexp, CurveAffine}; use crate::poly::{commitment::MSM, ipa::commitment::ParamsVerifierIPA}; use ff::Field; use group::Group; @@ -166,7 +166,7 @@ impl<'a, C: CurveAffine> MSM for MSMIPA<'a, C> { assert_eq!(scalars.len(), len); - best_multiexp_cpu(&scalars, &bases) + best_multiexp(&scalars, &bases) } fn bases(&self) -> Vec { diff --git a/halo2_proofs/src/poly/ipa/strategy.rs b/halo2_proofs/src/poly/ipa/strategy.rs index 82f727f06a..d2d1b3d364 100644 --- a/halo2_proofs/src/poly/ipa/strategy.rs +++ b/halo2_proofs/src/poly/ipa/strategy.rs @@ -2,7 +2,7 @@ use super::commitment::{IPACommitmentScheme, ParamsIPA}; use super::msm::MSMIPA; use super::multiopen::VerifierIPA; use crate::{ - arithmetic::best_multiexp_cpu, + arithmetic::best_multiexp, plonk::Error, poly::{ commitment::MSM, @@ -67,7 +67,7 @@ impl<'params, C: CurveAffine> GuardIPA<'params, C> { pub fn compute_g(&self) -> C { let s = compute_s(&self.u, C::Scalar::ONE); - best_multiexp_cpu(&s, &self.msm.params.g).to_affine() + best_multiexp(&s, &self.msm.params.g).to_affine() } } diff --git a/halo2_proofs/src/poly/kzg/commitment.rs b/halo2_proofs/src/poly/kzg/commitment.rs index 926b7adda6..9a70ed45bb 100644 --- a/halo2_proofs/src/poly/kzg/commitment.rs +++ b/halo2_proofs/src/poly/kzg/commitment.rs @@ -1,11 +1,4 @@ -use crate::arithmetic::{best_multiexp_cpu, g_to_lagrange, parallelize}; - -#[cfg(feature = "icicle_gpu")] -use crate::arithmetic::best_multiexp_gpu; -#[cfg(feature = "icicle_gpu")] -use crate::icicle; -#[cfg(feature = "icicle_gpu")] -use std::env; +use crate::arithmetic::{best_multiexp, g_to_lagrange, parallelize}; use crate::helpers::SerdeCurveAffine; use crate::poly::commitment::{Blind, CommitmentScheme, Params, ParamsProver, ParamsVerifier}; @@ -125,11 +118,6 @@ where g_lagrange }; - #[cfg(feature = "icicle_gpu")] - if env::var("ENABLE_ICICLE_GPU").is_ok() { - icicle::init_gpu::(&g, &g_lagrange); - } - let g2 = ::generator(); let s_g2 = (g2 * s).into(); @@ -164,11 +152,6 @@ where None => g_to_lagrange(g.iter().map(PrimeCurveAffine::to_curve).collect(), k), }; - #[cfg(feature = "icicle_gpu")] - if env::var("ENABLE_ICICLE_GPU").is_ok() { - icicle::init_gpu::(&g, &g_lagrange); - } - Self { k, n: 1 << k, @@ -279,11 +262,6 @@ where } }; - #[cfg(feature = "icicle_gpu")] - if env::var("ENABLE_ICICLE_GPU").is_ok() { - icicle::init_gpu::(&g, &g_lagrange); - } - let g2 = E::G2Affine::read(reader, format)?; let s_g2 = E::G2Affine::read(reader, format)?; @@ -340,15 +318,7 @@ where let size = scalars.len(); assert!(bases.len() >= size); - #[cfg(feature = "icicle_gpu")] - if env::var("ENABLE_ICICLE_GPU").is_ok() && !icicle::should_use_cpu_msm(size) { - best_multiexp_gpu::(&scalars, true) - } else { - best_multiexp_cpu(&scalars, &bases[0..size]) - } - - #[cfg(not(feature = "icicle_gpu"))] - best_multiexp_cpu(&scalars, &bases[0..size]) + best_multiexp(&scalars, &bases[0..size]) } /// Writes params to a buffer. @@ -393,15 +363,7 @@ where let size = scalars.len(); assert!(bases.len() >= size); - #[cfg(feature = "icicle_gpu")] - if env::var("ENABLE_ICICLE_GPU").is_ok() && !icicle::should_use_cpu_msm(size) { - best_multiexp_gpu::(&scalars, false) - } else { - best_multiexp_cpu(&scalars, &bases[0..size]) - } - - #[cfg(not(feature = "icicle_gpu"))] - best_multiexp_cpu(&scalars, &bases[0..size]) + best_multiexp(&scalars, &bases[0..size]) } fn get_g(&self) -> &[E::G1Affine] { diff --git a/halo2_proofs/src/poly/kzg/msm.rs b/halo2_proofs/src/poly/kzg/msm.rs index ae17bb1e62..f9b8c284bd 100644 --- a/halo2_proofs/src/poly/kzg/msm.rs +++ b/halo2_proofs/src/poly/kzg/msm.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use super::commitment::ParamsKZG; use crate::{ - arithmetic::{best_multiexp_cpu, parallelize}, + arithmetic::{best_multiexp, parallelize}, poly::commitment::MSM, }; use group::{Curve, Group}; @@ -81,7 +81,7 @@ where use group::prime::PrimeCurveAffine; let mut bases = vec![E::G1Affine::identity(); self.scalars.len()]; E::G1::batch_normalize(&self.bases, &mut bases); - best_multiexp_cpu(&self.scalars, &bases) + best_multiexp(&self.scalars, &bases) } fn bases(&self) -> Vec {