concretizer: rework spack solve output to handle reuse better
This commit is contained in:
parent
c537785f6f
commit
ace4586bf8
@ -122,13 +122,21 @@ def solve(parser, args):
|
|||||||
tty.msg("Best of %d considered solutions." % result.nmodels)
|
tty.msg("Best of %d considered solutions." % result.nmodels)
|
||||||
tty.msg("Optimization Criteria:")
|
tty.msg("Optimization Criteria:")
|
||||||
|
|
||||||
maxlen = max(len(s) for s in result.criteria)
|
maxlen = max(len(s[2]) for s in result.criteria)
|
||||||
color.cprint(
|
color.cprint(
|
||||||
"@*{ Priority Criterion %sValue}" % ((maxlen - 10) * " ")
|
"@*{ Priority Criterion %sInstalled ToBuild}" % ((maxlen - 10) * " ")
|
||||||
)
|
)
|
||||||
for i, (name, val) in enumerate(zip(result.criteria, opt)):
|
|
||||||
fmt = " @K{%%-8d} %%-%ds%%5d" % maxlen
|
fmt = " @K{%%-8d} %%-%ds%%9s %%7s" % maxlen
|
||||||
color.cprint(fmt % (i + 1, name, val))
|
for i, (idx, build_idx, name) in enumerate(result.criteria, 1):
|
||||||
|
color.cprint(
|
||||||
|
fmt % (
|
||||||
|
i,
|
||||||
|
name,
|
||||||
|
"-" if build_idx is None else opt[idx],
|
||||||
|
opt[idx] if build_idx is None else opt[build_idx],
|
||||||
|
)
|
||||||
|
)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
for spec in result.specs:
|
for spec in result.specs:
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
from __future__ import print_function
|
from __future__ import division, print_function
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
@ -92,6 +92,67 @@ def getter(node):
|
|||||||
'DeclaredVersion', ['version', 'idx', 'origin']
|
'DeclaredVersion', ['version', 'idx', 'origin']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Below numbers are used to map names of criteria to the order
|
||||||
|
# they appear in the solution. See concretize.lp
|
||||||
|
|
||||||
|
#: Priority offset for "build" criteria (regular criterio shifted to
|
||||||
|
#: higher priority for specs we have to build)
|
||||||
|
build_priority_offset = 200
|
||||||
|
|
||||||
|
#: Priority offset of "fixed" criteria (those w/o build criteria)
|
||||||
|
fixed_priority_offset = 100
|
||||||
|
|
||||||
|
|
||||||
|
def build_criteria_names(costs, tuples):
|
||||||
|
"""Construct an ordered mapping from criteria names to indices in the cost list."""
|
||||||
|
# pull optimization criteria names out of the solution
|
||||||
|
priorities_names = []
|
||||||
|
|
||||||
|
num_fixed = 0
|
||||||
|
for pred, args in tuples:
|
||||||
|
if pred != "opt_criterion":
|
||||||
|
continue
|
||||||
|
|
||||||
|
priority, name = args[:2]
|
||||||
|
priority = int(priority)
|
||||||
|
|
||||||
|
# add the priority of this opt criterion and its name
|
||||||
|
priorities_names.append((priority, name))
|
||||||
|
|
||||||
|
# if the priority is less than fixed_priority_offset, then it
|
||||||
|
# has an associated build priority -- the same criterion but for
|
||||||
|
# nodes that we have to build.
|
||||||
|
if priority < fixed_priority_offset:
|
||||||
|
build_priority = priority + build_priority_offset
|
||||||
|
priorities_names.append((build_priority, name))
|
||||||
|
else:
|
||||||
|
num_fixed += 1
|
||||||
|
|
||||||
|
# sort the criteria by priority
|
||||||
|
priorities_names = sorted(priorities_names, reverse=True)
|
||||||
|
|
||||||
|
assert len(priorities_names) == len(costs), "Wrong number of optimization criteria!"
|
||||||
|
|
||||||
|
# split list into three parts: build criteria, fixed criteria, non-build criteria
|
||||||
|
num_criteria = len(priorities_names)
|
||||||
|
num_build = (num_criteria - num_fixed) // 2
|
||||||
|
|
||||||
|
build = priorities_names[:num_build]
|
||||||
|
fixed = priorities_names[num_build:num_build + num_fixed]
|
||||||
|
installed = priorities_names[num_build + num_fixed:]
|
||||||
|
|
||||||
|
# mapping from priority to index in cost list
|
||||||
|
indices = dict((p, i) for i, (p, n) in enumerate(priorities_names))
|
||||||
|
|
||||||
|
# make a list that has each name with its build and non-build priority
|
||||||
|
criteria = [
|
||||||
|
(p - fixed_priority_offset + num_build, None, name) for p, name in fixed
|
||||||
|
]
|
||||||
|
for (i, name), (b, _) in zip(installed, build):
|
||||||
|
criteria.append((indices[i], indices[b], name))
|
||||||
|
|
||||||
|
return criteria
|
||||||
|
|
||||||
|
|
||||||
def issequence(obj):
|
def issequence(obj):
|
||||||
if isinstance(obj, string_types):
|
if isinstance(obj, string_types):
|
||||||
@ -531,13 +592,7 @@ def stringify(x):
|
|||||||
|
|
||||||
# add best spec to the results
|
# add best spec to the results
|
||||||
result.answers.append((list(min_cost), 0, answers))
|
result.answers.append((list(min_cost), 0, answers))
|
||||||
|
result.criteria = build_criteria_names(min_cost, tuples)
|
||||||
# pull optimization criteria names out of the solution
|
|
||||||
criteria = [
|
|
||||||
(int(args[0]), args[1]) for name, args in tuples
|
|
||||||
if name == "opt_criterion"
|
|
||||||
]
|
|
||||||
result.criteria = [t[1] for t in sorted(criteria, reverse=True)]
|
|
||||||
|
|
||||||
# record the number of models the solver considered
|
# record the number of models the solver considered
|
||||||
result.nmodels = len(models)
|
result.nmodels = len(models)
|
||||||
@ -1635,6 +1690,9 @@ def setup(self, driver, specs, tests=False, reuse=False):
|
|||||||
|
|
||||||
class SpecBuilder(object):
|
class SpecBuilder(object):
|
||||||
"""Class with actions to rebuild a spec from ASP results."""
|
"""Class with actions to rebuild a spec from ASP results."""
|
||||||
|
#: Attributes that don't need actions
|
||||||
|
ignored_attributes = ["opt_criterion"]
|
||||||
|
|
||||||
def __init__(self, specs):
|
def __init__(self, specs):
|
||||||
self._result = None
|
self._result = None
|
||||||
self._command_line_specs = specs
|
self._command_line_specs = specs
|
||||||
@ -1797,6 +1855,9 @@ def build_specs(self, function_tuples):
|
|||||||
|
|
||||||
self._specs = {}
|
self._specs = {}
|
||||||
for name, args in function_tuples:
|
for name, args in function_tuples:
|
||||||
|
if name in SpecBuilder.ignored_attributes:
|
||||||
|
continue
|
||||||
|
|
||||||
action = getattr(self, name, None)
|
action = getattr(self, name, None)
|
||||||
|
|
||||||
# print out unknown actions so we can display them for debugging
|
# print out unknown actions so we can display them for debugging
|
||||||
|
@ -793,7 +793,12 @@ build(Package) :- not hash(Package, _), node(Package).
|
|||||||
% defaults and preferences. This is implemented by bumping the priority of optimization
|
% defaults and preferences. This is implemented by bumping the priority of optimization
|
||||||
% criteria for built specs -- so that they take precedence over the otherwise
|
% criteria for built specs -- so that they take precedence over the otherwise
|
||||||
% topmost-priority criterion to reuse what is installed.
|
% topmost-priority criterion to reuse what is installed.
|
||||||
build_priority(Package, 100) :- build(Package), node(Package).
|
%
|
||||||
|
% The priority ranges are:
|
||||||
|
% 200+ Shifted priorities for build nodes; correspond to priorities 0 - 99.
|
||||||
|
% 100 - 199 Unshifted priorities. Currently only includes minimizing #builds.
|
||||||
|
% 0 - 99 Priorities for non-built nodes.
|
||||||
|
build_priority(Package, 200) :- build(Package), node(Package).
|
||||||
build_priority(Package, 0) :- not build(Package), node(Package).
|
build_priority(Package, 0) :- not build(Package), node(Package).
|
||||||
|
|
||||||
#defined installed_hash/2.
|
#defined installed_hash/2.
|
||||||
@ -807,18 +812,17 @@ build_priority(Package, 0) :- not build(Package), node(Package).
|
|||||||
% is displayed (clingo doesn't display sums over empty sets by default)
|
% is displayed (clingo doesn't display sums over empty sets by default)
|
||||||
|
|
||||||
% Try hard to reuse installed packages (i.e., minimize the number built)
|
% Try hard to reuse installed packages (i.e., minimize the number built)
|
||||||
opt_criterion(17, "number of packages to build (vs. reuse)").
|
opt_criterion(100, "number of packages to build (vs. reuse)").
|
||||||
#minimize { 0@17: #true }.
|
#minimize { 0@100: #true }.
|
||||||
#minimize { 1@17,Package : build(Package), optimize_for_reuse() }.
|
#minimize { 1@100,Package : build(Package), optimize_for_reuse() }.
|
||||||
#defined optimize_for_reuse/0.
|
#defined optimize_for_reuse/0.
|
||||||
|
|
||||||
% Minimize the number of deprecated versions being used
|
% Minimize the number of deprecated versions being used
|
||||||
opt_criterion(116, "(build) deprecated versions used").
|
opt_criterion(14, "deprecated versions used").
|
||||||
opt_criterion(16, "deprecated versions used").
|
#minimize{ 0@214: #true }.
|
||||||
#minimize{ 0@116: #true }.
|
#minimize{ 0@14: #true }.
|
||||||
#minimize{ 0@16: #true }.
|
|
||||||
#minimize{
|
#minimize{
|
||||||
1@16+Priority,Package
|
1@14+Priority,Package
|
||||||
: deprecated(Package, _),
|
: deprecated(Package, _),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
@ -827,33 +831,30 @@ opt_criterion(16, "deprecated versions used").
|
|||||||
% 1. Version weight
|
% 1. Version weight
|
||||||
% 2. Number of variants with a non default value, if not set
|
% 2. Number of variants with a non default value, if not set
|
||||||
% for the root(Package)
|
% for the root(Package)
|
||||||
opt_criterion(115, "(build) version weight").
|
opt_criterion(13, "version weight").
|
||||||
opt_criterion(15, "version weight").
|
#minimize{ 0@213: #true }.
|
||||||
#minimize{ 0@115: #true }.
|
#minimize{ 0@13: #true }.
|
||||||
#minimize{ 0@15: #true }.
|
|
||||||
#minimize {
|
#minimize {
|
||||||
Weight@15+Priority
|
Weight@13+Priority
|
||||||
: root(Package),version_weight(Package, Weight),
|
: root(Package),version_weight(Package, Weight),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
opt_criterion(114, "(build) number of non-default variants (roots)").
|
opt_criterion(12, "number of non-default variants (roots)").
|
||||||
opt_criterion(14, "number of non-default variants (roots)").
|
#minimize{ 0@212: #true }.
|
||||||
#minimize{ 0@114: #true }.
|
#minimize{ 0@12: #true }.
|
||||||
#minimize{ 0@14: #true }.
|
|
||||||
#minimize {
|
#minimize {
|
||||||
Weight@14+Priority,Package,Variant,Value
|
Weight@12+Priority,Package,Variant,Value
|
||||||
: variant_not_default(Package, Variant, Value, Weight),
|
: variant_not_default(Package, Variant, Value, Weight),
|
||||||
root(Package),
|
root(Package),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
opt_criterion(112, "(build) preferred providers for roots").
|
opt_criterion(11, "preferred providers for roots").
|
||||||
opt_criterion(12, "preferred providers for roots").
|
#minimize{ 0@211 : #true }.
|
||||||
#minimize{ 0@112 : #true }.
|
#minimize{ 0@11: #true }.
|
||||||
#minimize{ 0@12: #true }.
|
|
||||||
#minimize{
|
#minimize{
|
||||||
Weight@12+Priority,Provider,Virtual
|
Weight@11+Priority,Provider,Virtual
|
||||||
: provider_weight(Provider, Virtual, Weight),
|
: provider_weight(Provider, Virtual, Weight),
|
||||||
root(Provider),
|
root(Provider),
|
||||||
build_priority(Provider, Priority)
|
build_priority(Provider, Priority)
|
||||||
@ -862,12 +863,11 @@ opt_criterion(12, "preferred providers for roots").
|
|||||||
% If the value is a multivalued variant there could be multiple
|
% If the value is a multivalued variant there could be multiple
|
||||||
% values set as default. Since a default value has a weight of 0 we
|
% values set as default. Since a default value has a weight of 0 we
|
||||||
% need to maximize their number below to ensure they're all set
|
% need to maximize their number below to ensure they're all set
|
||||||
opt_criterion(111, "(build) number of values in multi-valued variants (root)").
|
opt_criterion(10, "number of values in multi-valued variants (root)").
|
||||||
opt_criterion(11, "number of values in multi-valued variants (root)").
|
#minimize{ 0@210 : #true }.
|
||||||
#minimize{ 0@111 : #true }.
|
#minimize{ 0@10 : #true }.
|
||||||
#minimize{ 0@11 : #true }.
|
|
||||||
#maximize {
|
#maximize {
|
||||||
1@11+Priority,Package,Variant,Value
|
1@10+Priority,Package,Variant,Value
|
||||||
: variant_not_default(Package, Variant, Value, Weight),
|
: variant_not_default(Package, Variant, Value, Weight),
|
||||||
not variant_single_value(Package, Variant),
|
not variant_single_value(Package, Variant),
|
||||||
root(Package),
|
root(Package),
|
||||||
@ -875,11 +875,11 @@ opt_criterion(11, "number of values in multi-valued variants (root)").
|
|||||||
}.
|
}.
|
||||||
|
|
||||||
% Try to use default variants or variants that have been set
|
% Try to use default variants or variants that have been set
|
||||||
opt_criterion(110, "(build) number of non-default variants (non-roots)").
|
opt_criterion(9, "number of non-default variants (non-roots)").
|
||||||
opt_criterion(10, "number of non-default variants (non-roots)").
|
#minimize{ 0@209: #true }.
|
||||||
#minimize{ 0@10: #true }.
|
#minimize{ 0@9: #true }.
|
||||||
#minimize {
|
#minimize {
|
||||||
Weight@10+Priority,Package,Variant,Value
|
Weight@9+Priority,Package,Variant,Value
|
||||||
: variant_not_default(Package, Variant, Value, Weight),
|
: variant_not_default(Package, Variant, Value, Weight),
|
||||||
not root(Package),
|
not root(Package),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
@ -887,62 +887,57 @@ opt_criterion(10, "number of non-default variants (non-roots)").
|
|||||||
|
|
||||||
% Minimize the weights of the providers, i.e. use as much as
|
% Minimize the weights of the providers, i.e. use as much as
|
||||||
% possible the most preferred providers
|
% possible the most preferred providers
|
||||||
opt_criterion(109, "(build) preferred providers (non-roots)").
|
opt_criterion(8, "preferred providers (non-roots)").
|
||||||
opt_criterion(9, "preferred providers (non-roots)").
|
#minimize{ 0@208: #true }.
|
||||||
#minimize{ 0@109: #true }.
|
#minimize{ 0@8: #true }.
|
||||||
#minimize{ 0@9: #true }.
|
|
||||||
#minimize{
|
#minimize{
|
||||||
Weight@9+Priority,Provider,Virtual
|
Weight@8+Priority,Provider,Virtual
|
||||||
: provider_weight(Provider, Virtual, Weight), not root(Provider),
|
: provider_weight(Provider, Virtual, Weight), not root(Provider),
|
||||||
build_priority(Provider, Priority)
|
build_priority(Provider, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
% Try to minimize the number of compiler mismatches in the DAG.
|
% Try to minimize the number of compiler mismatches in the DAG.
|
||||||
opt_criterion(108, "(build) compiler mismatches").
|
opt_criterion(7, "compiler mismatches").
|
||||||
opt_criterion(8, "compiler mismatches").
|
#minimize{ 0@207: #true }.
|
||||||
#minimize{ 0@108: #true }.
|
#minimize{ 0@7: #true }.
|
||||||
#minimize{ 0@8: #true }.
|
|
||||||
#minimize{
|
#minimize{
|
||||||
1@8+Priority,Package,Dependency
|
1@7+Priority,Package,Dependency
|
||||||
: compiler_mismatch(Package, Dependency),
|
: compiler_mismatch(Package, Dependency),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
% Try to minimize the number of compiler mismatches in the DAG.
|
% Try to minimize the number of compiler mismatches in the DAG.
|
||||||
opt_criterion(107, "(build) OS mismatches").
|
opt_criterion(6, "OS mismatches").
|
||||||
opt_criterion(7, "OS mismatches").
|
#minimize{ 0@206: #true }.
|
||||||
#minimize{ 0@107: #true }.
|
#minimize{ 0@6: #true }.
|
||||||
#minimize{ 0@7: #true }.
|
|
||||||
#minimize{
|
#minimize{
|
||||||
1@7+Priority,Package,Dependency
|
1@6+Priority,Package,Dependency
|
||||||
: node_os_mismatch(Package, Dependency),
|
: node_os_mismatch(Package, Dependency),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
opt_criterion(106, "(build) non-preferred OSes").
|
opt_criterion(5, "non-preferred OS's").
|
||||||
#minimize{ 0@106: #true }.
|
#minimize{ 0@205: #true }.
|
||||||
#minimize{ 0@6: #true }.
|
#minimize{ 0@5: #true }.
|
||||||
#minimize{
|
#minimize{
|
||||||
Weight@6+Priority,Package
|
Weight@5+Priority,Package
|
||||||
: node_os_weight(Package, Weight),
|
: node_os_weight(Package, Weight),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
% Choose more recent versions for nodes
|
% Choose more recent versions for nodes
|
||||||
opt_criterion(105, "(build) version badness").
|
|
||||||
opt_criterion(5, "version badness").
|
opt_criterion(5, "version badness").
|
||||||
#minimize{ 0@105: #true }.
|
#minimize{ 0@204: #true }.
|
||||||
#minimize{ 0@5: #true }.
|
#minimize{ 0@4: #true }.
|
||||||
#minimize{
|
#minimize{
|
||||||
Weight@5+Priority,Package
|
Weight@4+Priority,Package
|
||||||
: version_weight(Package, Weight),
|
: version_weight(Package, Weight),
|
||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
% Try to use preferred compilers
|
% Try to use preferred compilers
|
||||||
opt_criterion(103, "(build) non-preferred compilers").
|
|
||||||
opt_criterion(3, "non-preferred compilers").
|
opt_criterion(3, "non-preferred compilers").
|
||||||
#minimize{ 0@103: #true }.
|
#minimize{ 0@203: #true }.
|
||||||
#minimize{ 0@3: #true }.
|
#minimize{ 0@3: #true }.
|
||||||
#minimize{
|
#minimize{
|
||||||
Weight@3+Priority,Package
|
Weight@3+Priority,Package
|
||||||
@ -952,9 +947,8 @@ opt_criterion(3, "non-preferred compilers").
|
|||||||
|
|
||||||
% Minimize the number of mismatches for targets in the DAG, try
|
% Minimize the number of mismatches for targets in the DAG, try
|
||||||
% to select the preferred target.
|
% to select the preferred target.
|
||||||
opt_criterion(102, "(build) target mismatches").
|
|
||||||
opt_criterion(2, "target mismatches").
|
opt_criterion(2, "target mismatches").
|
||||||
#minimize{ 0@102: #true }.
|
#minimize{ 0@202: #true }.
|
||||||
#minimize{ 0@2: #true }.
|
#minimize{ 0@2: #true }.
|
||||||
#minimize{
|
#minimize{
|
||||||
1@2+Priority,Package,Dependency
|
1@2+Priority,Package,Dependency
|
||||||
@ -962,9 +956,8 @@ opt_criterion(2, "target mismatches").
|
|||||||
build_priority(Package, Priority)
|
build_priority(Package, Priority)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
opt_criterion(101, "(build) non-preferred targets").
|
|
||||||
opt_criterion(1, "non-preferred targets").
|
opt_criterion(1, "non-preferred targets").
|
||||||
#minimize{ 0@101: #true }.
|
#minimize{ 0@201: #true }.
|
||||||
#minimize{ 0@1: #true }.
|
#minimize{ 0@1: #true }.
|
||||||
#minimize{
|
#minimize{
|
||||||
Weight@1+Priority,Package
|
Weight@1+Priority,Package
|
||||||
|
Loading…
Reference in New Issue
Block a user