concretizer: handle target preferences from packages.yaml

The weight of the target used in concretization is, in order:
1. A specific per package weight, if set in packages.yaml
2. Inherited from the parent, if possible
3. The default target weight (always set)
This commit is contained in:
Massimiliano Culpo 2020-10-13 15:11:32 +02:00 committed by Todd Gamblin
parent 67344326c3
commit 9c23ed6484
2 changed files with 45 additions and 9 deletions

View file

@ -997,14 +997,13 @@ def external_packages(self):
self.gen.out.write(external_rule)
self.gen.control.add("base", [], external_rule)
def concretization_preferences(self, pkg_name):
def preferred_variants(self, pkg_name):
"""Facts on concretization preferences, as read from packages.yaml"""
preferences = spack.package_prefs.PackagePrefs
preferred_variants = preferences.preferred_variants(pkg_name)
if not preferred_variants:
return
self.gen.h2('Concretization preferences {0}'.format(pkg_name))
for variant_name in sorted(preferred_variants):
variant = preferred_variants[variant_name]
values = variant.value
@ -1017,6 +1016,21 @@ def concretization_preferences(self, pkg_name):
pkg_name, variant.name, value
))
def preferred_targets(self, pkg_name):
key_fn = spack.package_prefs.PackagePrefs(pkg_name, 'target')
target_specs = [
spack.spec.Spec('target={0}'.format(target_name))
for target_name in llnl.util.cpu.targets
]
preferred_targets = [x for x in target_specs if key_fn(x) < 0]
if not preferred_targets:
return
preferred = preferred_targets[0]
self.gen.fact(fn.package_target_weight(
str(preferred.architecture.target), pkg_name, -10
))
def flag_defaults(self):
self.gen.h2("Compiler flag defaults")
@ -1193,8 +1207,6 @@ def target_defaults(self, specs):
for compiler in sorted(compilers):
supported = self._supported_targets(compiler, compatible_targets)
# print(" ", compiler, "supports", [t.name for t in supported])
if not supported:
continue
@ -1227,10 +1239,10 @@ def target_defaults(self, specs):
# prefer best possible targets; weight others poorly so
# they're not used unless set explicitly
if target.name in best_targets:
self.gen.fact(fn.target_weight(target.name, i))
self.gen.fact(fn.default_target_weight(target.name, i))
i += 1
else:
self.gen.fact(fn.target_weight(target.name, 100))
self.gen.fact(fn.default_target_weight(target.name, 100))
self.gen.newline()
@ -1394,7 +1406,8 @@ def setup(self, driver, specs):
for pkg in sorted(pkgs):
self.gen.h2('Package: %s' % pkg)
self.pkg_rules(pkg)
self.concretization_preferences(pkg)
self.preferred_variants(pkg)
self.preferred_targets(pkg)
self.gen.h1('Spec Constraints')
for spec in sorted(specs):

View file

@ -235,6 +235,22 @@ node_os(Package, OS)
% one target per node -- optimization will pick the "best" one
1 { node_target(Package, Target) : target(Target) } 1 :- node(Package).
% The target weight is either the default target weight
% or a more specific per-package weight if set
target_weight(Target, Package, Weight)
:- default_target_weight(Target, Weight),
node(Package),
not derive_target_from_parent(_, Package),
not package_target_weight(Target, Package, _).
target_weight(Target, Dependency, Weight)
:- depends_on(Package, Dependency),
derive_target_from_parent(Package, Dependency),
target_weight(Target, Package, Weight).
target_weight(Target, Package, Weight)
:- package_target_weight(Target, Package, Weight).
% can't use targets on node if the compiler for the node doesn't support them
:- node_target(Package, Target),
not compiler_supports_target(Compiler, Version, Target),
@ -247,7 +263,9 @@ node_target(Package, Target)
% each node has the weight of its assigned target
node_target_weight(Package, Weight)
:- node(Package), node_target(Package, Target), target_weight(Target, Weight).
:- node(Package),
node_target(Package, Target),
target_weight(Target, Package, Weight).
% compatibility rules for targets among nodes
node_target_match_pref(Package, Target) :- node_target_set(Package, Target).
@ -257,7 +275,12 @@ node_target_match_pref(Dependency, Target)
node_target_match(Package, 1)
:- node_target(Package, Target), node_target_match_pref(Package, Target).
derive_target_from_parent(Parent, Package)
:- depends_on(Parent, Package), not package_target_weight(_, Package, _).
#defined node_target_set/2.
#defined package_target_weight/3.
%-----------------------------------------------------------------------------
% Compiler semantics
@ -422,7 +445,7 @@ root(Dependency, 1) :- not root(Dependency), node(Dependency).
% fastest target for node
% TODO: if these are slightly different by compiler (e.g., skylake is
% best, gcc supports skylake and broadweell, clang's best is haswell)
% best, gcc supports skylake and broadwell, clang's best is haswell)
% things seem to get really slow.
#maximize{ Weight@5,Package : node_target_match(Package, Weight) }.
#minimize{ Weight@4,Package : node_target_weight(Package, Weight) }.