Add virtual information on DAG edges#34821
Conversation
528dddc to
857754f
Compare
|
@tgamblin Do we want to reconstruct virtuals on edges when reading "old" specs in JSON format? I think that is possible in principle, since specs have a unique provider. |
|
We could also consider printing this info in |
dee0025 to
0b2db30
Compare
0b2db30 to
0d01503
Compare
0d01503 to
c2207c9
Compare
Extracted from spack#34821 This commit makes explicit the format version of the spec file we are reading from. Before there were different functions capable of reading some part of the spec file at multiple format versions. The decision was implicit, since checks were based on the structure of the JSON without ever checking a format version number. The refactor makes also explicit which spec file format is used by which database and lockfile format, since the information is stored in global mappings. To ensure we don't change the hash of old specs, JSON representations of specs have been added as data. A unit tests checks that we read the correct hash in, and that the hash stays the same when we re-serialize the spec using the most recent format version.
Extracted from spack#34821 This commit makes explicit the format version of the spec file we are reading from. Before there were different functions capable of reading some part of the spec file at multiple format versions. The decision was implicit, since checks were based on the structure of the JSON without ever checking a format version number. The refactor makes also explicit which spec file format is used by which database and lockfile format, since the information is stored in global mappings. To ensure we don't change the hash of old specs, JSON representations of specs have been added as data. A unit tests checks that we read the correct hash in, and that the hash stays the same when we re-serialize the spec using the most recent format version.
c2207c9 to
5a41fb2
Compare
lib/spack/spack/cray_manifest.py
Outdated
| # TODO: Check this with Peter | ||
| parent_spec._add_dependency(dep_spec, deptypes=deptypes, virtuals=()) |
There was a problem hiding this comment.
@scheibelp Is ☝️ correct when reading from a Cray manifest? Or are there cases where we read DAGs that should include virtual dependency annotations on edges?
There was a problem hiding this comment.
Virtual information would not be included in the manifest currently. If virtuals=(), does that mean that the dependency provides no virtuals (i.e. spec["mpi"] would fail for a dag that contains openmpi)? Or does it default to providing all the virtuals that it could provide?
There was a problem hiding this comment.
It means that the dependency provides no virtuals on the edge being added. Currently I didn't change any type of computation internal to Spack, so spec["mpi"] still works without looking at edge attributes - but I'm pretty sure that will change in the future.
When reading from previous formats I have added a function that tries to reconstruct the virtual attributes on edges:
Lines 4808 to 4817 in 5a41fb2
Should we do something similar for Cray too (or reuse the same function if possible)?
There was a problem hiding this comment.
It means that the dependency provides no virtuals on the edge being added.
I think we should probably default to inferring that all possible virtuals are provided, but perhaps the next bit will provide clarity on why I think that (and if I'm wrong).
Should we do something similar for Cray too (or reuse the same function if possible)?
Cray (specifically specs read from manifests on Cray machines) is not different from reading/using specs that were installed prior to this merge. I am confused by the notion that Cray-specific logic is needed:
- If a new install directly depends on a spec read from the manifest, I assume this PR could assign virtual information to the edges
- However, DAGs read from the manifest do not encode the virtual information on the edges, so Specs using these cannot select a subset of virtual functionality (i.e., if
X -> fooandfooprovidesblasandlapack, any package that usesXmust usefoofor bothblasandlapack)- I don't anticipate this will be a problem, as the manifest is primarily for describing things like
cray-libscithat are direct providers
- I don't anticipate this will be a problem, as the manifest is primarily for describing things like
Does that resolve the issue? Or am I missing something?
There was a problem hiding this comment.
@alalazo it seems like this would need the virtual inference that you use for reading old spec formats here.
0fa8e54 to
0d8a9eb
Compare
|
For reference, moving from the current
where appropriate. When moving from this PR back to develop, we'll see the following errors. Develop (e70755f)Bad error message for databases, understandable error message for environments. For databases: $ spack find
==> Error: Version("7")For environments: $ spack concretize
==> Error: Spack 0.20.0.dev0 cannot read environment lockfiles using the v5 formatreleases/v0.19 (9e8e725)Understandable error message for databases, bad error message for environments. For databases: $ spack find
==> Error: Expected database version 6 but found version 7.
`spack reindex` may fix this, or you may need a newer Spack version.For environments: $ spack concretize
==> Error: 'type'So not sure how to fix these properly. I'll post some tests with buildcaches tomorrow. |
|
moving this to 0.21, as it's a large change and we don't need it for 0.20. I think we need to get the safeguards in develop, 0.20, 0.19.3, then get this in soon after 0.20 |
b7929e7 to
141357c
Compare
becker33
left a comment
There was a problem hiding this comment.
We should probably note in the docs that this extension to the syntax doesn't work well with the old concretizer -- I only know of one user still using it and I think that will be zero pretty soon, but still worth noting. It looks like the syntax will work, but the virtual splitting looks like it will not. Is that accurate?
lib/spack/spack/cray_manifest.py
Outdated
| # TODO: Check this with Peter | ||
| parent_spec._add_dependency(dep_spec, deptypes=deptypes, virtuals=()) |
There was a problem hiding this comment.
@alalazo it seems like this would need the virtual inference that you use for reading old spec formats here.
| continue | ||
| current_spec[node.name].add_dependency_edge( | ||
| test_dependency.copy(), deptypes="test" | ||
| test_dependency.copy(), deptypes="test", virtuals=() |
There was a problem hiding this comment.
This seems like it would lose information if the package has a test dependency on a virtual? Am I missing something?
lib/spack/spack/test/concretize.py
Outdated
| def test_virtuals_are_annotated_on_edges(self, default_mock_concretization): | ||
| spec = default_mock_concretization("mpileaks ^mpich") | ||
|
|
||
| edges = spec.edges_to_dependencies(name="mpich") | ||
| assert len(edges) == 1 and edges[0].virtuals == ("mpi",) | ||
| edges = spec.edges_to_dependencies(name="callpath") | ||
| assert len(edges) == 1 and edges[0].virtuals == () |
There was a problem hiding this comment.
Can we make this test the case in which the dependency is found entirely by spack as well? Something like
| def test_virtuals_are_annotated_on_edges(self, default_mock_concretization): | |
| spec = default_mock_concretization("mpileaks ^mpich") | |
| edges = spec.edges_to_dependencies(name="mpich") | |
| assert len(edges) == 1 and edges[0].virtuals == ("mpi",) | |
| edges = spec.edges_to_dependencies(name="callpath") | |
| assert len(edges) == 1 and edges[0].virtuals == () | |
| @pytest.mark.parametrize("spec", ["mpileaks", "mpileaks ^mpich"]) | |
| def test_virtuals_are_annotated_on_edges(self, spec, default_mock_concretization): | |
| spec = default_mock_concretization(spec) | |
| mpiname = spec["mpi"].name | |
| edges = spec.edges_to_dependencies(name=mpiname) | |
| assert len(edges) == 1 and edges[0].virtuals == ("mpi",) | |
| edges = spec.edges_to_dependencies(name="callpath") | |
| assert len(edges) == 1 and edges[0].virtuals == () |
| yield self.parent.name if self.parent else None | ||
| yield self.spec.name if self.spec else None | ||
| yield self.deptypes | ||
| yield self.virtuals |
There was a problem hiding this comment.
Wouldn't it be more forward thinking to yield a dict of self.parameters?
There was a problem hiding this comment.
We can extend that when we'll work on use_variants and we'll introduce parameters other than these two. Using a dict requires us to make the object hashable, since:
>>> {} < {}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'dict' and 'dict'| # both the parent and the child. When we update this object they'll | ||
| # both see the deptype modification. | ||
| edge.add_type(deptypes) | ||
| edge.update_deptypes(deptypes=deptypes) |
There was a problem hiding this comment.
I think we should be able to update the virtual information here as well, is there a reason that's not implemented as part of this?
This works for both the new and the old concretizer. Also, added type hints to involved functions.
141357c to
9c31dea
Compare
This PR doesn't introduce any change in the spec syntax. It's just a preliminary change in the internal representation. #35322 is coded on top of this PR and introduces that change. Are you referring to that PR? |
|
Do we need to take any action on the Also, people using the develop buildcache with a commit preceding the eventual merge, will be unable to continue doing so. I think that is fine, since we also have |
Yes, I was conflating with that PR. |
Since spack#34821 we are annotating virtual dependencies on DAG edges, and reconstructing virtuals in mempry when we read a concrete spec from previous formats. Therefore, we can remove a TODO in asp.py, and rely on "virtual_on_edge" facts to be imposed.
Since #34821 we are annotating virtual dependencies on DAG edges, and reconstructing virtuals in memory when we read a concrete spec from previous formats. Therefore, we can remove a TODO in asp.py, and rely on "virtual_on_edge" facts to be imposed.
Since spack#34821 we are annotating virtual dependencies on DAG edges, and reconstructing virtuals in memory when we read a concrete spec from previous formats. Therefore, we can remove a TODO in asp.py, and rely on "virtual_on_edge" facts to be imposed.
depends on #34807
closes #35258
fixes #34886
Currently virtual dependencies are used only during concretization to select a provider. No annotation is kept on edges to reflect that a leaf node is providing a virtual dependency. This PR adds virtual information on edges, so we can keep track of which spec is providing what virtual both in memory and in the JSON / YAML representation.
An example entry in JSON format is:
Modifications:
virtualsattribute toDependencySpecSpec.to_node_dictto output information on virtuals in the `"dependencies" sectionDependencySpecto hold an arbitrary number of attributes (98b9806)