Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC for two passes of pilopt #2535

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

PoC for two passes of pilopt #2535

wants to merge 6 commits into from

Conversation

qwang98
Copy link
Collaborator

@qwang98 qwang98 commented Mar 11, 2025

After discussing with @Schaeff, we plan to have two pilopt passes, one before "backend aware tuning" and one after. In a chronological order:

  1. Linker will emit native bus interactions only.
  2. Pil analyzer
  3. First pass pilopt (potentially insert optimization for connections)
  4. (Optional) backend aware tuning: only executed if a backend argument is provided. For backends that can process native bus interactions (e.g. Stwo), directly send it down the pipeline without modification. For backends that can't, call multi_bus_linker, which creates bus columns/constraints and phantom bus interaction.
  5. (Optional) second pass pilopt, executed only if step 4 is run.

I do have one question:

  1. Will there be cases where the backend argument is not provided but a "default backend" which requires phantom bus interaction is still run? In this edge case, step 4 and 5 will not emit phantom bus interaction but the "default backend" still demands it. If this can happen, then this PR won't work. The fix would be simple though: just instantiate the default BackendFactory and call backend aware tuning on it.

Comment on lines +181 to +186

fn tune_analyzed_pil(&self, pil: Analyzed<F>) -> Analyzed<F> {
// TODO: currently defaults to the identity function
// Move `bus_multi_linker` calls here in the future
pil
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be an API for BackendFactory instead of Backend, because constructing Backend requires input witness etc., which aren't yet known at this point. BackendFactory is tied to the command line backend argument, which is appropriate for backend aware tuning which this API will include in the future.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense I think!

Comment on lines 971 to 977
let optimized_post_tuning_pil = if let Some(backend_type) = self.arguments.backend {
let factory = backend_type.factory::<T>();
let backend_tuned_pil = factory.tune_analyzed_pil(optimized_pre_tuning_pil);
powdr_pilopt::optimize(backend_tuned_pil)
} else {
optimized_pre_tuning_pil
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no backend argument is provided in the pipeline, this will simply return the same PIL (one pilopt pass instead of two).

@qwang98 qwang98 requested a review from Schaeff March 11, 2025 08:02
@chriseth
Copy link
Member

I'm wondering if it would make sense to make this a separate pipeline step / artefact

@qwang98
Copy link
Collaborator Author

qwang98 commented Mar 12, 2025

I'm wondering if it would make sense to make this a separate pipeline step / artefact

I also discussed this with @Schaeff and sounds good to us. :)

@qwang98
Copy link
Collaborator Author

qwang98 commented Mar 12, 2025

This new version is also a PoC and will fail tests. The work flow is: pilopt -> backend specific tuning -> pilopt -> witgen and etc. In this design, compute_witness (stage 0 witgen) will require knowing the backend type (there are stage 0 bus columns to generate for some backend types but not other types). This requirement is enforced by calling compute_backend_tuned_pil in compute_witness. However, this creates a new problem: many benchmarking/testing functions runs all the way till right before the backend. Previously, backend type is not required as stage 0 witgen is the same for all backends. Now, we would have to specify a backend type for these benchmarking/testing functions. I propose two solutions to address this:

  1. Default these benchmarking/testing functions to a backend type that requires stage 0 bus column witgen. This will be a "conservative" estimate of our benchmarks, because it has longer witgen than backends that use native bus interaction.
  2. Move bus witgen to the backend and run it as the first step of the backend. This removes the need for two passes of pilopt, because all "backend specific tuning" are now in the backend itself.

P.S. I made comments throughout the PR to mark these scenarios (which a lot more complicated than described above), so you can get a sense of the various cases we encounter here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants