From 64034264ee4d2886f0482b5bbd52b37915a4af7e Mon Sep 17 00:00:00 2001 From: Ratan Kaliani Date: Wed, 28 Feb 2024 23:32:43 -0800 Subject: [PATCH] speed up weierstrass --- .../weierstrass/weierstrass_double.rs | 82 ++++++++++++------ .../elf/riscv32im-succinct-zkvm-elf | Bin 85500 -> 88448 bytes tests/secp256k1-double/src/main.rs | 46 +++++----- 3 files changed, 78 insertions(+), 50 deletions(-) diff --git a/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs b/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs index ced770596d..62d29a0999 100644 --- a/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs +++ b/core/src/syscall/precompiles/weierstrass/weierstrass_double.rs @@ -27,9 +27,12 @@ use p3_field::AbstractField; use p3_field::PrimeField32; use p3_matrix::dense::RowMajorMatrix; use p3_matrix::MatrixRowSlices; +use p3_maybe_rayon::prelude::ParallelIterator; +use p3_maybe_rayon::prelude::ParallelSlice; use sp1_derive::AlignedBorrow; use std::fmt::Debug; use std::marker::PhantomData; +use tracing::instrument; pub const NUM_WEIERSTRASS_DOUBLE_COLS: usize = size_of::>(); @@ -162,41 +165,64 @@ impl MachineAir "WeierstrassDoubleAssign".to_string() } + #[instrument(name = "generate WeierstrassDoubleAssign trace", skip_all)] fn generate_trace( &self, input: &ExecutionRecord, output: &mut ExecutionRecord, ) -> RowMajorMatrix { - let mut rows = Vec::new(); - - let mut new_field_events = Vec::new(); - - for i in 0..input.weierstrass_double_events.len() { - let event = input.weierstrass_double_events[i]; - let mut row = [F::zero(); NUM_WEIERSTRASS_DOUBLE_COLS]; - let cols: &mut WeierstrassDoubleAssignCols = row.as_mut_slice().borrow_mut(); - - // Decode affine points. - let p = &event.p; - let p = AffinePoint::::from_words_le(p); - let (p_x, p_y) = (p.x, p.y); - - // Populate basic columns. - cols.is_real = F::one(); - cols.shard = F::from_canonical_u32(event.shard); - cols.clk = F::from_canonical_u32(event.clk); - cols.p_ptr = F::from_canonical_u32(event.p_ptr); - - Self::populate_field_ops(cols, p_x, p_y); - - // Populate the memory access columns. - for i in 0..NUM_WORDS_EC_POINT { - cols.p_access[i].populate(event.p_memory_records[i], &mut new_field_events); - } + let chunk_size = std::cmp::max( + input.weierstrass_double_events.len() / (num_cpus::get() * 2), + 1, + ); - rows.push(row); + // Generate the trace rows & corresponding records for each chunk of events in parallel. + let rows_and_records = input + .weierstrass_double_events + .par_chunks(chunk_size) + .map(|events| { + let mut record = ExecutionRecord::default(); + let mut new_field_events = Vec::new(); + + let rows = events + .iter() + .map(|event| { + let mut row = [F::zero(); NUM_WEIERSTRASS_DOUBLE_COLS]; + let cols: &mut WeierstrassDoubleAssignCols = + row.as_mut_slice().borrow_mut(); + + // Decode affine points. + let p = &event.p; + let p = AffinePoint::::from_words_le(p); + let (p_x, p_y) = (p.x, p.y); + + // Populate basic columns. + cols.is_real = F::one(); + cols.shard = F::from_canonical_u32(event.shard); + cols.clk = F::from_canonical_u32(event.clk); + cols.p_ptr = F::from_canonical_u32(event.p_ptr); + + Self::populate_field_ops(cols, p_x, p_y); + + // Populate the memory access columns. + for i in 0..NUM_WORDS_EC_POINT { + cols.p_access[i] + .populate(event.p_memory_records[i], &mut new_field_events); + } + row + }) + .collect::>(); + record.add_field_events(&new_field_events); + (rows, record) + }) + .collect::>(); + + // Generate the trace rows for each event. + let mut rows = Vec::new(); + for mut row_and_record in rows_and_records { + rows.extend(row_and_record.0); + output.append(&mut row_and_record.1); } - output.add_field_events(&new_field_events); pad_rows(&mut rows, || { let mut row = [F::zero(); NUM_WEIERSTRASS_DOUBLE_COLS]; diff --git a/tests/secp256k1-double/elf/riscv32im-succinct-zkvm-elf b/tests/secp256k1-double/elf/riscv32im-succinct-zkvm-elf index ec3c1d332aeb6af0619216dfa252b59f986d29df..e051cbb593cd380484994d39f84f2ebad215a3b2 100755 GIT binary patch delta 28009 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 diff --git a/tests/secp256k1-double/src/main.rs b/tests/secp256k1-double/src/main.rs index 52aa791145..fda6ac1a5f 100644 --- a/tests/secp256k1-double/src/main.rs +++ b/tests/secp256k1-double/src/main.rs @@ -6,31 +6,33 @@ extern "C" { } pub fn main() { - // generator. - // 55066263022277343669578718895168534326250603453777594175500187360389116729240 - // 32670510020758816978083085130507043184471273380659243275938904335757337482424 - let mut a: [u8; 64] = [ - 152, 23, 248, 22, 91, 129, 242, 89, 217, 40, 206, 45, 219, 252, 155, 2, 7, 11, 135, 206, - 149, 98, 160, 85, 172, 187, 220, 249, 126, 102, 190, 121, 184, 212, 16, 251, 143, 208, 71, - 156, 25, 84, 133, 166, 72, 180, 23, 253, 168, 8, 17, 14, 252, 251, 164, 93, 101, 196, 163, - 38, 119, 218, 58, 72, - ]; + for _ in 0..10i64.pow(3) { + // generator. + // 55066263022277343669578718895168534326250603453777594175500187360389116729240 + // 32670510020758816978083085130507043184471273380659243275938904335757337482424 + let mut a: [u8; 64] = [ + 152, 23, 248, 22, 91, 129, 242, 89, 217, 40, 206, 45, 219, 252, 155, 2, 7, 11, 135, + 206, 149, 98, 160, 85, 172, 187, 220, 249, 126, 102, 190, 121, 184, 212, 16, 251, 143, + 208, 71, 156, 25, 84, 133, 166, 72, 180, 23, 253, 168, 8, 17, 14, 252, 251, 164, 93, + 101, 196, 163, 38, 119, 218, 58, 72, + ]; - unsafe { - syscall_secp256k1_double(a.as_mut_ptr() as *mut u32); - } + unsafe { + syscall_secp256k1_double(a.as_mut_ptr() as *mut u32); + } - // 2 * generator. - // 89565891926547004231252920425935692360644145829622209833684329913297188986597 - // 12158399299693830322967808612713398636155367887041628176798871954788371653930 - let b: [u8; 64] = [ - 229, 158, 112, 92, 185, 9, 172, 171, 167, 60, 239, 140, 75, 142, 119, 92, 216, 124, 192, - 149, 110, 64, 69, 48, 109, 125, 237, 65, 148, 127, 4, 198, 42, 229, 207, 80, 169, 49, 100, - 35, 225, 208, 102, 50, 101, 50, 246, 247, 238, 234, 108, 70, 25, 132, 197, 163, 57, 195, - 61, 166, 254, 104, 225, 26, - ]; + // 2 * generator. + // 89565891926547004231252920425935692360644145829622209833684329913297188986597 + // 12158399299693830322967808612713398636155367887041628176798871954788371653930 + let b: [u8; 64] = [ + 229, 158, 112, 92, 185, 9, 172, 171, 167, 60, 239, 140, 75, 142, 119, 92, 216, 124, + 192, 149, 110, 64, 69, 48, 109, 125, 237, 65, 148, 127, 4, 198, 42, 229, 207, 80, 169, + 49, 100, 35, 225, 208, 102, 50, 101, 50, 246, 247, 238, 234, 108, 70, 25, 132, 197, + 163, 57, 195, 61, 166, 254, 104, 225, 26, + ]; - assert_eq!(a, b); + assert_eq!(a, b); + } println!("done"); }