@@ -635,7 +635,7 @@ pub trait IsStarkProver<
635635 air_trace_pairs : & [ AirTracePair < ' _ , Field , FieldExtension , PI > ] ,
636636 metadatas : & [ Round1Metadata < Field , FieldExtension > ] ,
637637 domains : & [ Domain < Field > ] ,
638- twiddle_caches : & [ LdeTwiddles < Field > ] ,
638+ twiddle_caches : & [ Arc < LdeTwiddles < Field > > ] ,
639639 main_pool : & mut [ Vec < FieldElement < Field > > ] ,
640640 aux_pool : & mut [ Vec < FieldElement < FieldExtension > > ] ,
641641 ) where
@@ -651,7 +651,13 @@ pub trait IsStarkProver<
651651 . zip ( domains. iter ( ) . zip ( twiddle_caches. iter ( ) ) )
652652 {
653653 let result = Self :: reconstruct_round1 (
654- * air, * trace, domain, metadata, twiddles, main_pool, aux_pool,
654+ * air,
655+ * trace,
656+ domain,
657+ metadata,
658+ & * * twiddles,
659+ main_pool,
660+ aux_pool,
655661 )
656662 . expect ( "reconstruct_round1 failed in debug-checks" ) ;
657663 temp_results. push ( result) ;
@@ -1512,24 +1518,42 @@ pub trait IsStarkProver<
15121518 let phase_start = Instant :: now ( ) ;
15131519
15141520 let mut domains = Vec :: with_capacity ( num_airs) ;
1515- let mut twiddle_caches: Vec < LdeTwiddles < Field > > = Vec :: with_capacity ( num_airs) ;
1521+ let mut twiddle_caches: Vec < Arc < LdeTwiddles < Field > > > = Vec :: with_capacity ( num_airs) ;
15161522 let mut max_main_cols = 0usize ;
15171523 let mut max_aux_cols = 0usize ;
15181524 let mut max_lde_size = 0usize ;
15191525
1526+ // Deduplicate twiddle caches: tables with identical domain parameters share one Arc.
1527+ // Key on (interpolation_domain_size, blowup_factor, coset_offset_bytes) because each
1528+ // affects the twiddle values: interpolation_domain_size sizes `inv` and `coset_weights`,
1529+ // blowup_factor sizes `fwd`, and coset_offset sets `coset_weights` values.
1530+ // coset_offset is serialized via AsBytes since FieldElement<F> does not impl Hash without
1531+ // a BaseType: Hash bound.
1532+ let mut twiddle_by_domain: std:: collections:: HashMap <
1533+ ( usize , usize , Vec < u8 > ) ,
1534+ Arc < LdeTwiddles < Field > > ,
1535+ > = std:: collections:: HashMap :: new ( ) ;
1536+
15201537 for ( air, trace, _pub_inputs) in & * air_trace_pairs {
15211538 let trace_length = trace. num_rows ( ) ;
15221539 let domain = new_domain ( * air, trace_length) ;
15231540
15241541 let lde_size = domain. interpolation_domain_size * domain. blowup_factor ;
1525- let twiddles = LdeTwiddles :: new ( & domain) ;
1542+ let key = (
1543+ domain. interpolation_domain_size ,
1544+ domain. blowup_factor ,
1545+ domain. coset_offset . as_bytes ( ) ,
1546+ ) ;
1547+ let twiddles = twiddle_by_domain
1548+ . entry ( key)
1549+ . or_insert_with ( || Arc :: new ( LdeTwiddles :: new ( & domain) ) ) ;
15261550
15271551 max_main_cols = max_main_cols. max ( trace. num_main_columns ) ;
15281552 max_aux_cols = max_aux_cols. max ( air. num_auxiliary_rap_columns ( ) ) ;
15291553 max_lde_size = max_lde_size. max ( lde_size) ;
15301554
15311555 domains. push ( domain) ;
1532- twiddle_caches. push ( twiddles) ;
1556+ twiddle_caches. push ( Arc :: clone ( twiddles) ) ;
15331557 }
15341558
15351559 // Allocate K independent LDE column buffer pool sets for parallel table processing.
@@ -1573,7 +1597,7 @@ pub trait IsStarkProver<
15731597 let idx = chunk_start + j;
15741598 let ( air, trace, _) = & air_trace_pairs[ idx] ;
15751599 let domain = & domains[ idx] ;
1576- let twiddles = & twiddle_caches[ idx] ;
1600+ let twiddles = & * twiddle_caches[ idx] ;
15771601
15781602 if air. is_preprocessed ( ) {
15791603 Self :: commit_preprocessed_trace (
@@ -1693,7 +1717,7 @@ pub trait IsStarkProver<
16931717 let idx = chunk_start + j;
16941718 let ( air, trace, _) = & air_trace_pairs[ idx] ;
16951719 let domain = & domains[ idx] ;
1696- let twiddles = & twiddle_caches[ idx] ;
1720+ let twiddles = & * twiddle_caches[ idx] ;
16971721
16981722 if air. has_aux_trace ( ) {
16991723 let num_aux_cols = trace. num_aux_columns ;
@@ -1809,7 +1833,7 @@ pub trait IsStarkProver<
18091833 let ( air, trace, pub_inputs) = & air_trace_pairs[ idx] ;
18101834 let metadata = & metadatas[ idx] ;
18111835 let domain = & domains[ idx] ;
1812- let twiddles = & twiddle_caches[ idx] ;
1836+ let twiddles = & * twiddle_caches[ idx] ;
18131837
18141838 #[ cfg( feature = "instruments" ) ]
18151839 let table_start = Instant :: now ( ) ;
0 commit comments