Add a top-level concretizer config scope and --fresh option#28468
Add a top-level concretizer config scope and --fresh option#28468
concretizer config scope and --fresh option#28468Conversation
0b2afb8 to
33ce9bd
Compare
33ce9bd to
4555ed2
Compare
|
I actually prefer Looking at this and #28470, I think it would be helpful to formulate as many possible concretization use cases as we possibly can. As of now, it's unclear to me if it makes sense to list these as booleans keys (i.e. some of these may not be compatible, or may not be binary). Here are some concretization schemes I think would be useful to have (names TBD): Determinism
I think "reuse all" is a good default here. Packages
Versions
See pypa/pip#8085 for some use cases for and debate on the minimal versions concretization option in pip. I would actually love this to ensure that my documented minimal supported versions remain up-to-date. This would also help to test Spack packages. Compilers
Variants
For minimal variants, imagine just how many packages would break if you turned off all of the Python variants, we already hit this with packages like OpenCV/boost. For maximal variants, imagine distributing PyTorch/TF binaries built for every supported cuda_arch. Architecture
If you can think of any other possible use cases, feel free to update this comment. Seeing these all laid out, it's unclear if it makes sense to have separate flags/keys for all of these or just a few flags/keys like |
4555ed2 to
2d101d9
Compare
|
@adamjstewart: I actually like all of these. They're all doable. Some of them (like compilers) require some information that we don't have yet (specifically, compatibility between compilers and compiler versions for different languages). It might be worth converting this list to a discussion someplace so we can keep it around. My worry is that we can't plan for all this. I can't really think of ways they won't work together (except minimizing and maximizing the same thing), so I'm not as worried about that, but naming them is going to be hard, and we need to get reuse as the default soon, so that we can switch to full hash and fix the current somewhat thrashy CI situation. E4S, it turns out, has around 30 builds that are in conflict with some other build -- in the sense that they share a DAG hash but not a full hash. We need that deployment model to start matching up -- we can't ignore build deps in our installs anymore, but I don't want to inflict that on users without default I would argue that I think if we do that, the only decision left here is "what do we call
One of the reasons I like
Do you have other suggestions? |
2d101d9 to
ae443f1
Compare
|
Yep, I definitely agree we should make
What about "reuse all" vs "reuse deps" vs "reuse none"? That set alone makes me wonder whether boolean key-value pairs make sense. We could have separate Another alternative to |
I agree it's not intuitive that these are mutually exclusive, and that's the main thing I don't like about |
|
For what it's worth, I like Also, @adamjstewart I love your suggestion for a |
|
I concur that |
|
All in all, I like both |
|
Another suggestion: go with @adamjstewart's suggestion above right away(#28468 (comment)) and make the CLI option something like |
|
+1 for |
|
|
|
I kicked off the poll with |
I think we can handle cases like this with, e.g.: Now: concretizer:
reuse: trueLater: concretizer:
reuse:
from: [env, global, caches]
only: [deps]
I know I said it was hard to transition from a string to a dict above, but it's fairly easy to do when you're expanding on the |
ae443f1 to
42db1d7
Compare
|
@adamjstewart: ok based on the Slack poll, I think I think the last thing that we might need here is docs. Anything else missing in your view? |
bec3d65 to
b61efd6
Compare
The solver has a lot of configuration associated with it. Rather than adding arguments to everything, we should encapsulate that in a class. This is the start of that work; it replaces `solve()` and its kwargs with a class and properties.
The concretizer is going to grow to have many more configuration, and we really need some structured config for that. * We have the `config:concretizer` option that chooses the solver, but extending that is awkward (we'd need to replace a string with a `dict`) and the solver choice will be deprecated eventually. * We have the `concretization` option in environments, but it's not a top-level config section -- it's just for environments, and it also only admits a string right now. To avoid overlapping with either of these and to allow the most extensibility in the future, this adds a new `concretizer` config section that can be used in and outside of environments. There is only one option right now: `reuse`. This can expand to include other options later. Likely, we will soon deprecate `config:concretizer` and warn when the user doesn't use `clingo`, and we will eventually (sometime later) move the `together` / `separately` options from `concretization` into the top-level `concretizer` section. This commit just adds the new section and schema. Fully wiring it up is TBD.
Config scopes were different for `config` and `mutable_config`, and `mutable_config` did not have a command line scope. - [x] Fix by consolidating the creation logic for the two fixtures.
`--reuse` was previously handled individually by each command that
needed it. We are growing more concretization options, and they'll
need their own section for commands that support them.
Now there are two concretization options:
* `--reuse`: Attempt to reuse packages from installs and buildcaches.
* `--fresh`: Opposite of reuse -- traditional spack install.
To handle thes, this PR adds a `ConfigSetAction` for `argparse`, so
that you can write argparse code like this:
```
subgroup.add_argument(
'--reuse', action=ConfigSetAction, dest="concretizer:reuse",
const=True, default=None,
help='reuse installed dependencies/buildcaches when possible'
)
```
With this, you don't need to add logic to pull the argument out and
handle it; the `ConfigSetAction` just does it for you. This can probably
be used to clean up some other commands later, as well.
Code that was previously passing `reuse=True` around everywhere has
been refactored to use config, and config is set from the CLI using
a new `add_concretizer_args()` function in `spack.cmd.common.arguments`.
- [x] Add `ConfigSetAction` to simplify concretizer config on the CLI
- [x] Refactor code so that it does not pass `reuse=True` to every function.
- [x] Refactor commands to use `add_concretizer_args()` and to pass
concretizer config using the config system.
* Document `concretizer.yaml`, `--reuse`, and `--fresh`.
b61efd6 to
dcb387f
Compare
5baccbe to
e584f4c
Compare
e584f4c to
dd7e562
Compare
064cc77 to
423c599
Compare
Reuse previously was a very invasive change that required parameters to be added to all
the methods that called `concretize()` on a `Spec` object. With the addition of
concretizer configuration, we can use the config system to simplify this argument
passing and keep the code cleaner.
We decided that concretizer config options should be read at `Solver` instantiation
time, and if config changes between instnatiation of a particular solver and
`solve()` invocation, the `Solver` should use the settings from `__init__()`.
- [x] remove `reuse` keyword argument from most concretize functions
- [x] refactor usages to use `spack.config.override("concretizer:reuse", True)`
- [x] rework argument passing in `Solver` so that parameters are set from config
at instantiation time
423c599 to
96fa4a2
Compare
| # If we're only doing setup, just return an empty solve result | ||
| if setup_only: | ||
| return Result(specs) | ||
|
|
There was a problem hiding this comment.
I think this is wrongly positioned, we should exit after we generated the error facts. I'll submit a bug fix asap.

We want to make
--reusethe default concretization strategy, but to do that we need to have some configuration so that users can revert if they need to. Also, the concretizer is going to grow to have many more options, and we really need some structured place to specify them.We currently have a couple places where concretizer options are specified (aside from the preferences in
packages.yaml):config:concretizeroption. This chooses the solver (clingoororiginal).concretizationoption in environments. This is not a top-level config section -- it's just for environments.Extending either of these is awkward -- both are simple strings and we'd need to deprecate (or work around) the old config options to expand them into more extensive YAML options. Also, we'd eventually like to have one place where concretizer configuration is specified.
To avoid overlapping with either of these and to allow the most extensibility in the future, this adds a new
concretizerconfig section that can be used in and outside of environments. There are two options right now:reuseandminimal. This can expand later. My expectation is that we will soon deprecateconfig:concretizerand warn when the user doesn't useclingo, and we will eventually (sometime later) move thetogether/separatelyoptions fromconcretizationinto the top-levelconcretizersection.concretizer.yamlcurrently looks like this:Stay tuned for additional options like
--minimal.And there are two options on
spack install,spack spec, etc.:--freshis there for when we make--reusethe default. I could not think of a more intuitive way to express what Spack's default install routine, but here is the rationale -- see if you like it:--upgradedidn't fully capture it (you might be "side-grading" or just re-concretizing).--newfor "new installation", but it might also reuse if there's a hash match, so--newdidn't seem completely right.--reuse-- e.g., people with CI use cases or nix/guix purists -- would call the default Spack install "deterministic", because it doesn't consider installation state. It's reproducible for the same spack version and packages.--deterministicand--reproducibleseem too technical.So I settled on
--fresh, because I think it captures what we're doing -- making a fresh install from the latest packages. It also gives us a term we can use pretty easily.When we make
--reusethe default, it'll make more sense, as Spack will tend to reuse what you already have, and you may want to start with a completely--freshinstall once those installations become too old.There are a few additional technical refactors in here to make this stuff easier; the details of those are in the commit messages.
spack.solver.asp.solve()into a classconcretizerconfig section and defaultconcretizer.yamlconftest.pyConfigSetActionto automatically set config options withargparseadd_concretizer_args()method to make concretizer arg handling consistent across commands--freshconcretizer arg