@@ -379,28 +379,26 @@ void build_constraints_parallel(UltraCircuitBuilder& builder,
379379 std::vector<TaskBlockSizes> task_sizes;
380380 std::vector<size_t > task_profile_indices;
381381
382- // Helper: given a constraint vector, a handler, and a key function, profile unique keys
383- // and return a map from key to profile index. Does NOT add tasks (that happens in order below).
384- auto profile_grouped = [&](auto & items, auto handler, auto key_fn) -> std::map<decltype (key_fn (items[0 ])), size_t > {
382+ // Helper: profile unique keys in a constraint vector, then add tasks in vector order.
383+ // Combines profiling and task collection in a single call per constraint type.
384+ auto profile_and_collect = [&](auto & items, auto handler, auto key_fn) {
385+ if (items.empty ()) {
386+ return ;
387+ }
385388 using Key = decltype (key_fn (items[0 ]));
386389 std::map<Key, size_t > key_to_profile;
390+ // Phase 1: profile unique keys
387391 for (size_t i = 0 ; i < items.size (); i++) {
388392 Key k = key_fn (items[i]);
389393 if (key_to_profile.count (k) == 0 ) {
390394 auto profile = profile_constraint_type (items[i], handler, num_witnesses);
391- size_t profile_idx = profiles.size ();
395+ key_to_profile[k] = profiles.size ();
392396 profiles.push_back (profile);
393- key_to_profile[k] = profile_idx;
394397 }
395398 }
396- return key_to_profile;
397- };
398-
399- // Helper: add tasks for a constraint vector in vector order, looking up each instance's profile.
400- auto collect_tasks = [&](auto & items, auto handler, const auto & key_to_profile, auto key_fn) {
399+ // Phase 1b: add tasks in vector order
401400 for (size_t i = 0 ; i < items.size (); i++) {
402- auto k = key_fn (items[i]);
403- size_t profile_idx = key_to_profile.at (k);
401+ size_t profile_idx = key_to_profile.at (key_fn (items[i]));
404402 const auto & profile = profiles[profile_idx];
405403 auto sizes = profile.block_sizes ;
406404 sizes.num_rom_arrays = profile.num_rom_arrays_per_instance ;
@@ -466,72 +464,22 @@ void build_constraints_parallel(UltraCircuitBuilder& builder,
466464 };
467465 auto ec_add_handler = [](UltraCircuitBuilder& b, const EcAdd& c) { create_ec_add_constraint (b, c); };
468466
469- // Profile all types (order doesn't matter here — just building the key→profile maps)
470- auto quad_profiles = !constraints.quad_constraints .empty ()
471- ? profile_grouped (constraints.quad_constraints , quad_handler, const_key)
472- : decltype (profile_grouped (constraints.quad_constraints , quad_handler, const_key)){};
473- auto big_quad_profiles =
474- !constraints.big_quad_constraints .empty ()
475- ? profile_grouped (constraints.big_quad_constraints , big_quad_handler, big_quad_key)
476- : decltype (profile_grouped (constraints.big_quad_constraints , big_quad_handler, big_quad_key)){};
477- auto logic_profiles = !constraints.logic_constraints .empty ()
478- ? profile_grouped (constraints.logic_constraints , logic_handler, logic_key)
479- : decltype (profile_grouped (constraints.logic_constraints , logic_handler, logic_key)){};
480- auto range_profiles = !constraints.range_constraints .empty ()
481- ? profile_grouped (constraints.range_constraints , range_handler, range_key)
482- : decltype (profile_grouped (constraints.range_constraints , range_handler, range_key)){};
483- auto aes_profiles = !constraints.aes128_constraints .empty ()
484- ? profile_grouped (constraints.aes128_constraints , aes_handler, aes_key)
485- : decltype (profile_grouped (constraints.aes128_constraints , aes_handler, aes_key)){};
486- auto sha_profiles = !constraints.sha256_compression .empty ()
487- ? profile_grouped (constraints.sha256_compression , sha_handler, const_key)
488- : decltype (profile_grouped (constraints.sha256_compression , sha_handler, const_key)){};
489- auto ecdsa_k1_profiles =
490- !constraints.ecdsa_k1_constraints .empty ()
491- ? profile_grouped (constraints.ecdsa_k1_constraints , ecdsa_k1_handler, const_key)
492- : decltype (profile_grouped (constraints.ecdsa_k1_constraints , ecdsa_k1_handler, const_key)){};
493- auto ecdsa_r1_profiles =
494- !constraints.ecdsa_r1_constraints .empty ()
495- ? profile_grouped (constraints.ecdsa_r1_constraints , ecdsa_r1_handler, const_key)
496- : decltype (profile_grouped (constraints.ecdsa_r1_constraints , ecdsa_r1_handler, const_key)){};
497- auto blake2s_profiles =
498- !constraints.blake2s_constraints .empty ()
499- ? profile_grouped (constraints.blake2s_constraints , blake2s_handler, blake2s_key)
500- : decltype (profile_grouped (constraints.blake2s_constraints , blake2s_handler, blake2s_key)){};
501- auto blake3_profiles =
502- !constraints.blake3_constraints .empty ()
503- ? profile_grouped (constraints.blake3_constraints , blake3_handler, blake3_key)
504- : decltype (profile_grouped (constraints.blake3_constraints , blake3_handler, blake3_key)){};
505- auto keccak_profiles =
506- !constraints.keccak_permutations .empty ()
507- ? profile_grouped (constraints.keccak_permutations , keccak_handler, const_key)
508- : decltype (profile_grouped (constraints.keccak_permutations , keccak_handler, const_key)){};
509- auto pos2_profiles = !constraints.poseidon2_constraints .empty ()
510- ? profile_grouped (constraints.poseidon2_constraints , pos2_handler, pos2_key)
511- : decltype (profile_grouped (constraints.poseidon2_constraints , pos2_handler, pos2_key)){};
512- auto msm_profiles =
513- !constraints.multi_scalar_mul_constraints .empty ()
514- ? profile_grouped (constraints.multi_scalar_mul_constraints , msm_handler, msm_key)
515- : decltype (profile_grouped (constraints.multi_scalar_mul_constraints , msm_handler, msm_key)){};
516- auto ec_add_profiles = !constraints.ec_add_constraints .empty ()
517- ? profile_grouped (constraints.ec_add_constraints , ec_add_handler, const_key)
518- : decltype (profile_grouped (constraints.ec_add_constraints , ec_add_handler, const_key)){};
519-
520- // Collect tasks in the same order as sequential build_constraints
521- collect_tasks (constraints.quad_constraints , quad_handler, quad_profiles, const_key);
522- collect_tasks (constraints.big_quad_constraints , big_quad_handler, big_quad_profiles, big_quad_key);
523- collect_tasks (constraints.logic_constraints , logic_handler, logic_profiles, logic_key);
524- collect_tasks (constraints.range_constraints , range_handler, range_profiles, range_key);
525- collect_tasks (constraints.aes128_constraints , aes_handler, aes_profiles, aes_key);
526- collect_tasks (constraints.sha256_compression , sha_handler, sha_profiles, const_key);
527- collect_tasks (constraints.ecdsa_k1_constraints , ecdsa_k1_handler, ecdsa_k1_profiles, const_key);
528- collect_tasks (constraints.ecdsa_r1_constraints , ecdsa_r1_handler, ecdsa_r1_profiles, const_key);
529- collect_tasks (constraints.blake2s_constraints , blake2s_handler, blake2s_profiles, blake2s_key);
530- collect_tasks (constraints.blake3_constraints , blake3_handler, blake3_profiles, blake3_key);
531- collect_tasks (constraints.keccak_permutations , keccak_handler, keccak_profiles, const_key);
532- collect_tasks (constraints.poseidon2_constraints , pos2_handler, pos2_profiles, pos2_key);
533- collect_tasks (constraints.multi_scalar_mul_constraints , msm_handler, msm_profiles, msm_key);
534- collect_tasks (constraints.ec_add_constraints , ec_add_handler, ec_add_profiles, const_key);
467+ // Profile and collect tasks in the same order as sequential build_constraints.
468+ // Each call profiles unique keys, then adds tasks in constraint vector order.
469+ profile_and_collect (constraints.quad_constraints , quad_handler, const_key);
470+ profile_and_collect (constraints.big_quad_constraints , big_quad_handler, big_quad_key);
471+ profile_and_collect (constraints.logic_constraints , logic_handler, logic_key);
472+ profile_and_collect (constraints.range_constraints , range_handler, range_key);
473+ profile_and_collect (constraints.aes128_constraints , aes_handler, aes_key);
474+ profile_and_collect (constraints.sha256_compression , sha_handler, const_key);
475+ profile_and_collect (constraints.ecdsa_k1_constraints , ecdsa_k1_handler, const_key);
476+ profile_and_collect (constraints.ecdsa_r1_constraints , ecdsa_r1_handler, const_key);
477+ profile_and_collect (constraints.blake2s_constraints , blake2s_handler, blake2s_key);
478+ profile_and_collect (constraints.blake3_constraints , blake3_handler, blake3_key);
479+ profile_and_collect (constraints.keccak_permutations , keccak_handler, const_key);
480+ profile_and_collect (constraints.poseidon2_constraints , pos2_handler, pos2_key);
481+ profile_and_collect (constraints.multi_scalar_mul_constraints , msm_handler, msm_key);
482+ profile_and_collect (constraints.ec_add_constraints , ec_add_handler, const_key);
535483
536484 // Phase 2: Prepare the builder's caches from profiles (no constraint execution).
537485 prepare_builder_from_profiles (builder, profiles);
0 commit comments