-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
concretizer: reuse existing packages #25310
Conversation
8d40878
to
fab5fae
Compare
Thanks @tgamblin, you have no idea how happy this makes me! Gave this a quick spin, here are my thoughts. CLII definitely think this should be configurable from the command-line. Can we move the option into P.S. When are we merging ConfigurationSince most Spack users will want to install things many times, I think this flag should be configurable in
Is this still something you think we should do? I would actually love to make the entire optimization criteria API public so that I can configure the order in my On this thread, the behavior I would personally like doesn't exactly fall under DefaultSince we're planning on switching the default concretizer in 0.17, and since concretization will change as a result anyway, I think we have a rare opportunity to change default concretization behavior without worrying too much about backwards compatibility. I think BugsThis PR seems to drastically change concretization behavior. That's expected, since develop, no reuse$ spack solve -I python
==> Best of 10 considered solutions.
==> Optimization Criteria:
Priority Criterion Value
1 deprecated versions used 0
2 version weight 0
3 number of non-default variants (roots) 0
4 multi-valued variants 0
5 preferred providers for roots 0
6 number of non-default variants (non-roots) 0
7 preferred providers (non-roots) 20
8 compiler mismatches 0
9 version badness -1
10 count of non-root multi-valued variants -2
11 non-preferred compilers 0
12 target mismatches 0
13 non-preferred targets -600
[+] python@3.8.11%apple-clang@12.0.0+bz2+ctypes+dbm~debug+libxml2+lzma~nis~optimizations+pic+pyexpat+pythoncmd+readline+shared+sqlite3+ssl~tix~tkinter~ucs4+uuid+zlib patches=0d98e93189bc278fbc37a50ed7f183bd8aaf249a8e1670a465f0db6bb4f8cf87 arch=darwin-catalina-x86_64
[+] ^apple-libuuid@1353.100.2%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^bzip2@1.0.8%apple-clang@12.0.0~debug~pic+shared arch=darwin-catalina-x86_64
[+] ^diffutils@3.7%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^libiconv@1.16%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^expat@2.4.1%apple-clang@12.0.0~libbsd arch=darwin-catalina-x86_64
[+] ^gdbm@1.19%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^readline@8.1%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^ncurses@6.2%apple-clang@12.0.0~symlinks+termlib abi=none arch=darwin-catalina-x86_64
[+] ^pkgconf@1.7.4%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^gettext@0.21%apple-clang@12.0.0+bzip2+curses+git~libunistring+libxml2+tar+xz arch=darwin-catalina-x86_64
[+] ^libxml2@2.9.10%apple-clang@12.0.0~python arch=darwin-catalina-x86_64
[+] ^xz@5.2.5%apple-clang@12.0.0~pic libs=shared,static arch=darwin-catalina-x86_64
[+] ^zlib@1.2.11%apple-clang@12.0.0+optimize+pic+shared arch=darwin-catalina-x86_64
[+] ^tar@1.34%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^libffi@3.3%apple-clang@12.0.0 patches=26f26c6f29a7ce9bf370ad3ab2610f99365b4bdd7b82e7c31df41a3370d685c0 arch=darwin-catalina-x86_64
[+] ^openssl@1.1.1k%apple-clang@12.0.0~docs+systemcerts arch=darwin-catalina-x86_64
[+] ^perl@5.34.0%apple-clang@12.0.0+cpanm+shared+threads arch=darwin-catalina-x86_64
[+] ^berkeley-db@18.1.40%apple-clang@12.0.0+cxx~docs+stl patches=b231fcc4d5cff05e5c3a4814f6a5af0e9a966428dc2176540d2c05aff41de522 arch=darwin-catalina-x86_64
[+] ^sqlite@3.35.5%apple-clang@12.0.0+column_metadata+fts~functions~rtree arch=darwin-catalina-x86_64 this branch, no reuse$ spack solve -I python
==> Best of 8 considered solutions.
==> Optimization Criteria:
Priority Criterion Value
1 number of packages to build (vs. reuse) 4
2 deprecated versions used 0
3 version weight 0
4 number of non-default variants (roots) 10
5 multi-valued variants 0
6 preferred providers for roots 0
7 number of non-default variants (non-roots) 4
8 preferred providers (non-roots) 20
9 compiler mismatches 0
10 OS mismatches 0
11 non-preferred OSes 0
12 version badness -1
13 count of non-root multi-valued variants 0
14 non-preferred compilers 0
15 target mismatches 0
16 non-preferred targets -150
- python@3.8.11%apple-clang@12.0.0~bz2~ctypes~dbm~debug~libxml2~lzma~nis~optimizations+pic~pyexpat+pythoncmd~readline+shared~sqlite3~ssl~tix~tkinter~ucs4+uuid~zlib patches=0d98e93189bc278fbc37a50ed7f183bd8aaf249a8e1670a465f0db6bb4f8cf87 arch=darwin-catalina-x86_64
[+] ^apple-libuuid@1353.100.2%apple-clang@12.0.0 arch=darwin-catalina-x86_64
- ^gettext@0.21%apple-clang@12.0.0~bzip2~curses+git~libunistring~libxml2~tar~xz arch=darwin-catalina-x86_64
[+] ^libiconv@1.16%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^pkgconf@1.7.4%apple-clang@12.0.0 arch=darwin-catalina-x86_64 this branch, reuse$ spack solve -I --reuse python
==> Best of 3 considered solutions.
==> Optimization Criteria:
Priority Criterion Value
1 number of packages to build (vs. reuse) 0
2 deprecated versions used 0
3 version weight 0
4 number of non-default variants (roots) 1
5 multi-valued variants -1
6 preferred providers for roots 0
7 number of non-default variants (non-roots) 1
8 preferred providers (non-roots) 0
9 compiler mismatches 0
10 OS mismatches 0
11 non-preferred OSes 0
12 version badness -1
13 count of non-root multi-valued variants -3
14 non-preferred compilers 0
15 target mismatches 0
16 non-preferred targets -480
[+] python@3.8.11%apple-clang@12.0.0+bz2+ctypes+dbm~debug+libxml2+lzma~nis~optimizations+pic+pyexpat+pythoncmd+readline+shared+sqlite3+ssl~tix~tkinter~ucs4+uuid+zlib patches=0d98e93189bc278fbc37a50ed7f183bd8aaf249a8e1670a465f0db6bb4f8cf87 arch=darwin-catalina-x86_64
[+] ^apple-libuuid@1353.100.2%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^bzip2@1.0.8%apple-clang@12.0.0~debug~pic+shared arch=darwin-catalina-x86_64
[+] ^expat@2.4.1%apple-clang@12.0.0~libbsd arch=darwin-catalina-x86_64
[+] ^gdbm@1.19%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^readline@8.1%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^ncurses@6.2%apple-clang@12.0.0~symlinks+termlib abi=none arch=darwin-catalina-x86_64
[+] ^gettext@0.21%apple-clang@12.0.0+bzip2+curses+git~libunistring+libxml2+tar+xz arch=darwin-catalina-x86_64
[+] ^libiconv@1.16%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^libxml2@2.9.10%apple-clang@12.0.0~python arch=darwin-catalina-x86_64
[+] ^xz@5.2.5%apple-clang@12.0.0~pic libs=shared,static arch=darwin-catalina-x86_64
[+] ^zlib@1.2.11%apple-clang@12.0.0+optimize+pic+shared arch=darwin-catalina-x86_64
[+] ^tar@1.34%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^libffi@3.3%apple-clang@12.0.0 patches=26f26c6f29a7ce9bf370ad3ab2610f99365b4bdd7b82e7c31df41a3370d685c0 arch=darwin-catalina-x86_64
[+] ^openssl@1.1.1k%apple-clang@12.0.0~docs+systemcerts arch=darwin-catalina-x86_64
[+] ^sqlite@3.35.5%apple-clang@12.0.0+column_metadata+fts~functions~rtree arch=darwin-catalina-x86_64 It seems that even when |
Yep this was true. It would not have any installations to consider, but it would minimize the number of built packages -- and everything was built so this boiled down to minimizing nodes as the top priority. Pushed a fix for just this problem. I would still like to make the reuse a bit smarter -- basically I would like it to aggressively reuse when possible, without minimizing builds quite so aggressively. I am not sure I really know how to structure the optimization criteria to get that result, but I'm thinking about it. |
Will this resolve multiple dependency spec issues such as the one reported for
|
@tldahlgren @tgamblin Fyi, I moved all the pipelines to clingo in #25502 and I encounter several errors similar to #25310 (comment), see e.g. https://gitlab.spack.io/spack/spack/-/jobs/659647 |
I haven't looked into whether it's feasible yet, but I think what we want for the optimization criteria is a heuristic for how unlikely we are to care about something -- for example, we could score each node by the minimal depth to traverse from the root to the node, and then put the optimization "cost" of building that node at We may also want to prioritize default variants for root packages above minimizing builds, but default variants for non-root packages below minimizing builds. That seems to track more with what we think we're doing when we install a package "unconstrained" (I want the default for the package, and then as efficient as possible to build deps). I'll start looking into how feasible this is in case people like it. |
I also agree with @adamjstewart that we want to make these options as configurable as possible. I don't think we want to expose the API for this because it's probably not sufficiently user friends to make a good user interface, but we should basically create a config option for every decision that we feel is non-obvious what people will want, because that probably means different people will want different things. |
Another thought -- if we want to minimize the extent to which turning off default variants improves the score without preventing the concretizer from toggling variants to get better reuse, we could combine the variant issue into the criterion. The "score" for the reuse optimization criterion could be something like In general I think some of our optimization criteria may be too complicated to be modeled at discrete priorities, and we may need to write more complicated fitness functions to explore the trade-offs in the space. Those fitness functions could well be named and selected by config options, to get back to the point Adam was making. |
Thinking about this more, I think the default behavior probably does not require a complicated priority-mixing fitness function, because I think my earlier idea about alternating the priority |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial review
lib/spack/spack/solver/asp.py
Outdated
@@ -1086,18 +1100,30 @@ def os_defaults(self, specs): | |||
platform = spack.architecture.platform() | |||
|
|||
# create set of OS's to consider | |||
possible = set([ | |||
buildable = set([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should include everything from platform.operating_systems.values()
. That's really the list of operating systems we could target from this build node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this was addressed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This worked with platform.operating_sys.keys()
return ( | ||
os == platform.default_os, # prefer default | ||
os not in buildable, # then prefer buildables | ||
os, # then sort by name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need a much more formal model of what a compatible
os is before we can try to mix operating systems in a meaningful way -- I think we currently get away with it because we put the OS optimization at such a high priority that the algorithm never chooses something else, but if we really want to allow centos7
binaries to be selected for rhel7
nodes we need a module for operating system compatibility which we can call into to compare any two operating systems and determine whether binaries for the first can run on the second. Then we could populate our possible_oses
list with something like all the operating systems that we know could run on any of the operating systems in the buildable
list.
ac9dfd8
to
6a40b97
Compare
@adamjstewart @alalazo I still need to clean this up a bit, rework how I'll write up a better description of how this works later, but short story is that now the opt criteria are structured like this:
The idea is that if we build nothing, all the criteria in (1) are zero. If we do build something, then the top priority is making the build specs look like we've come to expect (i.e., criteria in (1)), but we still prioritize reusing to satisfy their dependencies. This will still reuse as much as possible, as reusing will always be "as good" as the best possible build configuration (because all the criteria are minimizing and their best value is zero). No build configuration will be inherently better than reusing because reusing will not worsen any criteria in (1). It's a bit hard to think about at first but once you get the idea that the reused specs can't make the criteria in (1) worse, and (2) dominates the optimization process until we determine that something has to be built, it starts to make sense. |
@haampie can you give this a try as well? |
Hey Todd, I'll have a look on Monday! |
@tgamblin with the latest commit, all calls to
Also, I'm not seeing any dependency reuse anymore. $ spack solve -I py-torch
/Users/Adam/spack/lib/spack/spack/solver/concretize.lp:840:7-40: info: atom does not occur in any rule head:
provider_weight(Provider,Weight)
==> Best of 12 considered solutions.
==> Optimization Criteria:
Priority Criterion Value
1 (build) deprecated versions used 0
2 (build) version weight 0
3 (build) number of non-default variants (roots) 0
4 (build) preferred providers for roots 0
5 (build) preferred providers for roots 0
6 (build) number of non-default variants (non-roots) 0
7 (build) preferred providers (non-roots) 0
8 (build) compiler mismatches 0
9 (build) OS mismatches 0
10 (build) non-preferred OSes 0
11 (build) version badness 5
12 (build) non-preferred compilers 0
13 (build) target mismatches 0
14 (build) non-preferred targets -1230
15 number of packages to build (vs. reuse) 0
16 deprecated versions used 0
17 version weight 0
18 number of non-default variants (roots) 0
19 preferred providers for roots 0
20 preferred providers for roots 0
21 number of non-default variants (non-roots) 0
22 preferred providers (non-roots) 0
23 compiler mismatches 0
24 OS mismatches 0
25 version badness 0
26 non-preferred compilers 0
27 target mismatches 0
28 non-preferred targets 0
- py-torch@1.9.1%apple-clang@12.0.0+caffe2~cuda~cudnn~distributed~fbgemm~gloo+kineto~magma+metal+mkldnn~mpi~nccl+nnpack~numa+numpy+onnx_ml+openmp+qnnpack~rocm~tensorpipe~test~valgrind+xnnpack cuda_arch=none patches=e37afffe45cf7594c22050109942370e49983ad772d12ebccf508377dc9dcfc9 arch=darwin-catalina-x86_64
[+] ^cmake@3.21.3%apple-clang@12.0.0~doc+ncurses+openssl+ownlibs~qt build_type=Release arch=darwin-catalina-x86_64
[+] ^ncurses@6.2%apple-clang@12.0.0~symlinks+termlib abi=none arch=darwin-catalina-x86_64
[+] ^pkgconf@1.8.0%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^openssl@1.1.1l%apple-clang@12.0.0~docs certs=system arch=darwin-catalina-x86_64
[+] ^perl@5.34.0%apple-clang@12.0.0+cpanm+shared+threads arch=darwin-catalina-x86_64
[+] ^berkeley-db@18.1.40%apple-clang@12.0.0+cxx~docs+stl patches=b231fcc4d5cff05e5c3a4814f6a5af0e9a966428dc2176540d2c05aff41de522 arch=darwin-catalina-x86_64
[+] ^bzip2@1.0.8%apple-clang@12.0.0~debug~pic+shared arch=darwin-catalina-x86_64
[+] ^diffutils@3.8%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^libiconv@1.16%apple-clang@12.0.0 libs=shared,static arch=darwin-catalina-x86_64
[+] ^gdbm@1.19%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^readline@8.1%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^zlib@1.2.11%apple-clang@12.0.0+optimize+pic+shared arch=darwin-catalina-x86_64
[+] ^eigen@3.4.0%apple-clang@12.0.0~ipo build_type=RelWithDebInfo arch=darwin-catalina-x86_64
[+] ^fxdiv@2020-04-17%apple-clang@12.0.0~ipo build_type=RelWithDebInfo arch=darwin-catalina-x86_64
[+] ^ninja@1.10.2%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^python@3.8.11%apple-clang@12.0.0+bz2+ctypes+dbm~debug+libxml2+lzma~nis~optimizations+pic+pyexpat+pythoncmd+readline+shared+sqlite3+ssl~tix~tkinter~ucs4+uuid+zlib patches=0d98e93189bc278fbc37a50ed7f183bd8aaf249a8e1670a465f0db6bb4f8cf87,4c2457325f2b608b1b6a2c63087df8c26e07db3e3d493caf36a56f0ecf6fb768,f2fd060afc4b4618fe8104c4c5d771f36dc55b1db5a4623785a4ea707ec72fb4 arch=darwin-catalina-x86_64
[+] ^apple-libuuid@1353.100.2%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^expat@2.4.1%apple-clang@12.0.0~libbsd arch=darwin-catalina-x86_64
[+] ^gettext@0.21%apple-clang@12.0.0+bzip2+curses+git~libunistring+libxml2+tar+xz arch=darwin-catalina-x86_64
[+] ^libxml2@2.9.12%apple-clang@12.0.0~python arch=darwin-catalina-x86_64
[+] ^xz@5.2.5%apple-clang@12.0.0~pic libs=shared,static arch=darwin-catalina-x86_64
[+] ^tar@1.34%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^libffi@3.3%apple-clang@12.0.0 patches=26f26c6f29a7ce9bf370ad3ab2610f99365b4bdd7b82e7c31df41a3370d685c0 arch=darwin-catalina-x86_64
[+] ^sqlite@3.36.0%apple-clang@12.0.0+column_metadata+fts~functions~rtree arch=darwin-catalina-x86_64
[+] ^intel-mkl@2020.0.166%apple-clang@12.0.0~ilp64+shared threads=none arch=darwin-catalina-x86_64
[+] ^llvm-openmp@12.0.1%apple-clang@12.0.0~ipo~multicompat build_type=RelWithDebInfo arch=darwin-catalina-x86_64
[+] ^protobuf@3.18.0%apple-clang@12.0.0+shared build_type=Release arch=darwin-catalina-x86_64
[+] ^psimd@2020-05-17%apple-clang@12.0.0~ipo build_type=RelWithDebInfo arch=darwin-catalina-x86_64
[+] ^pthreadpool@2021-04-13%apple-clang@12.0.0~ipo build_type=RelWithDebInfo arch=darwin-catalina-x86_64
[+] ^py-future@0.18.2%apple-clang@12.0.0 arch=darwin-catalina-x86_64
- ^py-setuptools@57.4.0%apple-clang@12.0.0 arch=darwin-catalina-x86_64
- ^py-numpy@1.21.2%apple-clang@12.0.0+blas+lapack patches=873745d7b547857fcfec9cae90b09c133b42a4f0c23b6c2d84cf37e2dd816604 arch=darwin-catalina-x86_64
- ^py-cython@0.29.24%apple-clang@12.0.0 arch=darwin-catalina-x86_64
- ^py-protobuf@3.17.3%apple-clang@12.0.0~cpp arch=darwin-catalina-x86_64
[+] ^py-six@1.16.0%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^py-pybind11@2.6.2%apple-clang@12.0.0~ipo build_type=RelWithDebInfo arch=darwin-catalina-x86_64
[+] ^py-pyyaml@5.3.1%apple-clang@12.0.0+libyaml arch=darwin-catalina-x86_64
[+] ^libyaml@0.2.5%apple-clang@12.0.0 arch=darwin-catalina-x86_64
- ^py-tqdm@4.62.3%apple-clang@12.0.0~notebook~telegram arch=darwin-catalina-x86_64
- ^py-setuptools-scm@6.0.1%apple-clang@12.0.0+toml arch=darwin-catalina-x86_64
[+] ^py-toml@0.10.2%apple-clang@12.0.0 arch=darwin-catalina-x86_64
[+] ^py-typing-extensions@3.10.0.0%apple-clang@12.0.0 arch=darwin-catalina-x86_64 |
@adamjstewart can you test with the provider weight thing needs to be fixed with a |
This comment has been minimized.
This comment has been minimized.
CNL, debian6 and Suse are not compatible
- [x] Get rid of forgotten maximize directive. - [x] Simplify variant handling - [x] Fix bug in treatment of defaults on externals (don't count non-default variants on externals against them)
…auses In switching to hash facts for concrete specs, we lost the transitive facts from dependencies. This was fine for solves, because they were implied by the imposed constraints from every hash. However, for `spack diff`, we want to see what the hashes mean, so we need another mode for `spec_clauses()` to show that. This adds a `expand_hashes` argument to `spec_clauses()` that allows us to output *both* the hashes and their implications on dependencies. We use this mode in `spack diff`.
… rules Concrete specs that are already installed or that come from a buildcache may have compilers and variant settings that we do not recognize, but that shouldn't prevent reuse (at least not until we have a more detailed compiler model). - [x] make sure compiler and variant consistency rules only apply to built specs - [x] don't validate concrete specs on input, either -- they're concrete and we shouldn't apply today's rules to yesterday's build
In our tests, we use concrete specs generated from mock packages, which *only* occur as inputs to the solver. This fixes two problems: 1. We weren't previously adding facts to encode the necessary `depends_on()` relationships, and specs were unsatisfiable on reachability. 2. Our hash lookup for reconstructing the DAG does not consider that a hash may have come from the inputs.
Reformulate variant rules so that we minimize both 1. The number of non-default values being used 2. The number of default values not-being used This is crucial for MV variants where we may have more than one default value
Add docs for `--reuse`, along with a warning that it will likely be removed and refactored.
a38e368
to
2978c0f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked the last commits and gave this PR another fast test-drive. LGTM.
Congrats all for getting this in. I followed the dev conversation from a far. I'm excited to try this out. 🥳 |
Draft PR because it still needs some work, but it's in a state that @adamjstewart could start playing with.
Fixes #311.
Fixes #22613.
Fixes #20429.
This PR makes the concretizer aware of already-installed packages, and it tries to optimize the solve by reusing them instead of building when it can.
--reuse
optionCurrently, this adds a
--reuse
option tospack solve
. You can try it out withspack solve -Il --reuse <spec>
. I think the interface is TBD; we probably want to think about what to call this vs. the old solve, and about which one should be default.Minimizing builds
The way this works is:
It looks kind of like this
openssl
example, but for everything that is installed:openssl
, it also forces a bunch of constraints and a dependency on its particularzlib
installation on the solve. i.e., it's concrete -- we have to use it the way it was built and we cannot twiddle things like variant values on things we already installed.OS handling
The solver was still handling OS defaults through hard constraints (this is how we did it before we knew how to do it the right way -- with optimization), so this reworks OS handling in the solver. I believe this is the last part of the spec that needed converting -- targets and compilers were already changed in past PRs.
We now optimize for OS matches in the Spec, but we allow you to depend on a package for an older OS, with some limits. Specifically, I noticed when testing this that I wanted to reuse still-working Catalina installations on Big Sur. This adds the ability to specify, e.g.:
os_compatible("catalina", "bigsur")
so that the solver knows that it can safely reuse certain packages. I think we can also leverage this for, e.g., reusing CentOS binaries on RHEL.Relaxing existing constraints
Many of the existing constraints in the solver are meant for things we plan to build. When reusing concrete specs, We have to take the installed specs as they are. We can't do things like disallow unknown variant names (the variants may not exist) or compiler version OS support (we only know about the compilers on the current system, not the ones the concrete specs were built with). So, these types of constraints have been restricted to only apply to specs we intend to build. If we reuse something concrete, we still have to consider things like dependency version constraints (e.g. if you want to reuse
openssl
you should still check if the version that's installed satisfies yourdepends_on("openssl@:1.0")
constraint).Example
Here's a comparison of reusing vs. not reusing with
llvm
:With reuse:
`spack solve -Il --reuse llvm` output
Without reuse:
`spack solve -Il llvm` output
You can see we reuse a lot more with the reuse option on -- whereas without it Spack wants to build clean versions of everything but
zlib
. You can see this in the optimization criteria as well -- the difference between using--reuse
and not is 16 built packages. In the case without--reuse
, we're just not telling the solver about the installed packages so it has no hashes to swap in for different builds.Optimization criteria
There are still some tricky things in here -- specifically around the priority of these optimizations. You can see in the solve calls above that we're optimizing by minimizing the number of packages built. That has some weird consequences for things that aren't installed yet, like:
Here, the concretizer decided to disable
openssl
on a new cmake install, to avoid installing more things. So it did exactly what we told it to, but not what we likely want. We probably need to add some nuance to the optimization criterion. In particular, sometimes you care more about default variants, and sometimes you'd rather it reuse what's already installed.Currently, I am thinking we want to only minimize builds if something that is installed could be reused. If there's some package we already have to build, we should just respect its defaults and build dependencies as we normally would. I haven't worked out how best to model that yet or if it'll end up fitting peoples' intuition, so please provide suggestions.
On a similar note, you can see that we also used a couple of deprecated versions of things because they were already installed. Seems like maybe we should put the reuse optimization below the "don't use deprecated versions" optimization so that this won't happen. That would mean that you'd need to be explicit on the command line about using deprecated versions to get them into the solve. I suspect that might surprise some people so I'm not sure whether we shouldn't just warn instead.
Tasks
--reuse
-- should the old way be--deterministic
?--upgrade
?--latest
?)spack install
--reuse
to docsThat last task will make build caches and upstreams significantly easier to use the way we intended them, and it'll mean that you can both pull from
develop
and easily reuse binaries from older versions of Spack. This will reduce the perception of "hashes changing" that people have with the old, more deterministic concretizer.