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:
parent
67344326c3
commit
9c23ed6484
@ -997,14 +997,13 @@ def external_packages(self):
|
|||||||
self.gen.out.write(external_rule)
|
self.gen.out.write(external_rule)
|
||||||
self.gen.control.add("base", [], 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"""
|
"""Facts on concretization preferences, as read from packages.yaml"""
|
||||||
preferences = spack.package_prefs.PackagePrefs
|
preferences = spack.package_prefs.PackagePrefs
|
||||||
preferred_variants = preferences.preferred_variants(pkg_name)
|
preferred_variants = preferences.preferred_variants(pkg_name)
|
||||||
if not preferred_variants:
|
if not preferred_variants:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.gen.h2('Concretization preferences {0}'.format(pkg_name))
|
|
||||||
for variant_name in sorted(preferred_variants):
|
for variant_name in sorted(preferred_variants):
|
||||||
variant = preferred_variants[variant_name]
|
variant = preferred_variants[variant_name]
|
||||||
values = variant.value
|
values = variant.value
|
||||||
@ -1017,6 +1016,21 @@ def concretization_preferences(self, pkg_name):
|
|||||||
pkg_name, variant.name, value
|
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):
|
def flag_defaults(self):
|
||||||
self.gen.h2("Compiler flag defaults")
|
self.gen.h2("Compiler flag defaults")
|
||||||
|
|
||||||
@ -1193,8 +1207,6 @@ def target_defaults(self, specs):
|
|||||||
for compiler in sorted(compilers):
|
for compiler in sorted(compilers):
|
||||||
supported = self._supported_targets(compiler, compatible_targets)
|
supported = self._supported_targets(compiler, compatible_targets)
|
||||||
|
|
||||||
# print(" ", compiler, "supports", [t.name for t in supported])
|
|
||||||
|
|
||||||
if not supported:
|
if not supported:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -1227,10 +1239,10 @@ def target_defaults(self, specs):
|
|||||||
# prefer best possible targets; weight others poorly so
|
# prefer best possible targets; weight others poorly so
|
||||||
# they're not used unless set explicitly
|
# they're not used unless set explicitly
|
||||||
if target.name in best_targets:
|
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
|
i += 1
|
||||||
else:
|
else:
|
||||||
self.gen.fact(fn.target_weight(target.name, 100))
|
self.gen.fact(fn.default_target_weight(target.name, 100))
|
||||||
|
|
||||||
self.gen.newline()
|
self.gen.newline()
|
||||||
|
|
||||||
@ -1394,7 +1406,8 @@ def setup(self, driver, specs):
|
|||||||
for pkg in sorted(pkgs):
|
for pkg in sorted(pkgs):
|
||||||
self.gen.h2('Package: %s' % pkg)
|
self.gen.h2('Package: %s' % pkg)
|
||||||
self.pkg_rules(pkg)
|
self.pkg_rules(pkg)
|
||||||
self.concretization_preferences(pkg)
|
self.preferred_variants(pkg)
|
||||||
|
self.preferred_targets(pkg)
|
||||||
|
|
||||||
self.gen.h1('Spec Constraints')
|
self.gen.h1('Spec Constraints')
|
||||||
for spec in sorted(specs):
|
for spec in sorted(specs):
|
||||||
|
@ -235,6 +235,22 @@ node_os(Package, OS)
|
|||||||
% one target per node -- optimization will pick the "best" one
|
% one target per node -- optimization will pick the "best" one
|
||||||
1 { node_target(Package, Target) : target(Target) } 1 :- node(Package).
|
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
|
% can't use targets on node if the compiler for the node doesn't support them
|
||||||
:- node_target(Package, Target),
|
:- node_target(Package, Target),
|
||||||
not compiler_supports_target(Compiler, Version, 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
|
% each node has the weight of its assigned target
|
||||||
node_target_weight(Package, Weight)
|
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
|
% compatibility rules for targets among nodes
|
||||||
node_target_match_pref(Package, Target) :- node_target_set(Package, Target).
|
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_match(Package, 1)
|
||||||
:- node_target(Package, Target), node_target_match_pref(Package, Target).
|
:- 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 node_target_set/2.
|
||||||
|
#defined package_target_weight/3.
|
||||||
|
|
||||||
%-----------------------------------------------------------------------------
|
%-----------------------------------------------------------------------------
|
||||||
% Compiler semantics
|
% Compiler semantics
|
||||||
@ -422,7 +445,7 @@ root(Dependency, 1) :- not root(Dependency), node(Dependency).
|
|||||||
% fastest target for node
|
% fastest target for node
|
||||||
|
|
||||||
% TODO: if these are slightly different by compiler (e.g., skylake is
|
% 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.
|
% things seem to get really slow.
|
||||||
#maximize{ Weight@5,Package : node_target_match(Package, Weight) }.
|
#maximize{ Weight@5,Package : node_target_match(Package, Weight) }.
|
||||||
#minimize{ Weight@4,Package : node_target_weight(Package, Weight) }.
|
#minimize{ Weight@4,Package : node_target_weight(Package, Weight) }.
|
||||||
|
Loading…
Reference in New Issue
Block a user