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("Optimization Criteria:")
|
||||
|
||||
maxlen = max(len(s) for s in result.criteria)
|
||||
maxlen = max(len(s[2]) for s in result.criteria)
|
||||
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
|
||||
color.cprint(fmt % (i + 1, name, val))
|
||||
|
||||
fmt = " @K{%%-8d} %%-%ds%%9s %%7s" % maxlen
|
||||
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()
|
||||
|
||||
for spec in result.specs:
|
||||
|
@ -2,7 +2,7 @@
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
from __future__ import print_function
|
||||
from __future__ import division, print_function
|
||||
|
||||
import collections
|
||||
import copy
|
||||
@ -92,6 +92,67 @@ def getter(node):
|
||||
'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):
|
||||
if isinstance(obj, string_types):
|
||||
@ -531,13 +592,7 @@ def stringify(x):
|
||||
|
||||
# add best spec to the results
|
||||
result.answers.append((list(min_cost), 0, answers))
|
||||
|
||||
# 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)]
|
||||
result.criteria = build_criteria_names(min_cost, tuples)
|
||||
|
||||
# record the number of models the solver considered
|
||||
result.nmodels = len(models)
|
||||
@ -1635,6 +1690,9 @@ def setup(self, driver, specs, tests=False, reuse=False):
|
||||
|
||||
class SpecBuilder(object):
|
||||
"""Class with actions to rebuild a spec from ASP results."""
|
||||
#: Attributes that don't need actions
|
||||
ignored_attributes = ["opt_criterion"]
|
||||
|
||||
def __init__(self, specs):
|
||||
self._result = None
|
||||
self._command_line_specs = specs
|
||||
@ -1797,6 +1855,9 @@ def build_specs(self, function_tuples):
|
||||
|
||||
self._specs = {}
|
||||
for name, args in function_tuples:
|
||||
if name in SpecBuilder.ignored_attributes:
|
||||
continue
|
||||
|
||||
action = getattr(self, name, None)
|
||||
|
||||
# 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
|
||||
% criteria for built specs -- so that they take precedence over the otherwise
|
||||
% 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).
|
||||
|
||||
#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)
|
||||
|
||||
% Try hard to reuse installed packages (i.e., minimize the number built)
|
||||
opt_criterion(17, "number of packages to build (vs. reuse)").
|
||||
#minimize { 0@17: #true }.
|
||||
#minimize { 1@17,Package : build(Package), optimize_for_reuse() }.
|
||||
opt_criterion(100, "number of packages to build (vs. reuse)").
|
||||
#minimize { 0@100: #true }.
|
||||
#minimize { 1@100,Package : build(Package), optimize_for_reuse() }.
|
||||
#defined optimize_for_reuse/0.
|
||||
|
||||
% Minimize the number of deprecated versions being used
|
||||
opt_criterion(116, "(build) deprecated versions used").
|
||||
opt_criterion(16, "deprecated versions used").
|
||||
#minimize{ 0@116: #true }.
|
||||
#minimize{ 0@16: #true }.
|
||||
opt_criterion(14, "deprecated versions used").
|
||||
#minimize{ 0@214: #true }.
|
||||
#minimize{ 0@14: #true }.
|
||||
#minimize{
|
||||
1@16+Priority,Package
|
||||
1@14+Priority,Package
|
||||
: deprecated(Package, _),
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
@ -827,33 +831,30 @@ opt_criterion(16, "deprecated versions used").
|
||||
% 1. Version weight
|
||||
% 2. Number of variants with a non default value, if not set
|
||||
% for the root(Package)
|
||||
opt_criterion(115, "(build) version weight").
|
||||
opt_criterion(15, "version weight").
|
||||
#minimize{ 0@115: #true }.
|
||||
#minimize{ 0@15: #true }.
|
||||
opt_criterion(13, "version weight").
|
||||
#minimize{ 0@213: #true }.
|
||||
#minimize{ 0@13: #true }.
|
||||
#minimize {
|
||||
Weight@15+Priority
|
||||
Weight@13+Priority
|
||||
: root(Package),version_weight(Package, Weight),
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
|
||||
opt_criterion(114, "(build) number of non-default variants (roots)").
|
||||
opt_criterion(14, "number of non-default variants (roots)").
|
||||
#minimize{ 0@114: #true }.
|
||||
#minimize{ 0@14: #true }.
|
||||
opt_criterion(12, "number of non-default variants (roots)").
|
||||
#minimize{ 0@212: #true }.
|
||||
#minimize{ 0@12: #true }.
|
||||
#minimize {
|
||||
Weight@14+Priority,Package,Variant,Value
|
||||
Weight@12+Priority,Package,Variant,Value
|
||||
: variant_not_default(Package, Variant, Value, Weight),
|
||||
root(Package),
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
|
||||
opt_criterion(112, "(build) preferred providers for roots").
|
||||
opt_criterion(12, "preferred providers for roots").
|
||||
#minimize{ 0@112 : #true }.
|
||||
#minimize{ 0@12: #true }.
|
||||
opt_criterion(11, "preferred providers for roots").
|
||||
#minimize{ 0@211 : #true }.
|
||||
#minimize{ 0@11: #true }.
|
||||
#minimize{
|
||||
Weight@12+Priority,Provider,Virtual
|
||||
Weight@11+Priority,Provider,Virtual
|
||||
: provider_weight(Provider, Virtual, Weight),
|
||||
root(Provider),
|
||||
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
|
||||
% 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
|
||||
opt_criterion(111, "(build) number of values in multi-valued variants (root)").
|
||||
opt_criterion(11, "number of values in multi-valued variants (root)").
|
||||
#minimize{ 0@111 : #true }.
|
||||
#minimize{ 0@11 : #true }.
|
||||
opt_criterion(10, "number of values in multi-valued variants (root)").
|
||||
#minimize{ 0@210 : #true }.
|
||||
#minimize{ 0@10 : #true }.
|
||||
#maximize {
|
||||
1@11+Priority,Package,Variant,Value
|
||||
1@10+Priority,Package,Variant,Value
|
||||
: variant_not_default(Package, Variant, Value, Weight),
|
||||
not variant_single_value(Package, Variant),
|
||||
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
|
||||
opt_criterion(110, "(build) number of non-default variants (non-roots)").
|
||||
opt_criterion(10, "number of non-default variants (non-roots)").
|
||||
#minimize{ 0@10: #true }.
|
||||
opt_criterion(9, "number of non-default variants (non-roots)").
|
||||
#minimize{ 0@209: #true }.
|
||||
#minimize{ 0@9: #true }.
|
||||
#minimize {
|
||||
Weight@10+Priority,Package,Variant,Value
|
||||
Weight@9+Priority,Package,Variant,Value
|
||||
: variant_not_default(Package, Variant, Value, Weight),
|
||||
not root(Package),
|
||||
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
|
||||
% possible the most preferred providers
|
||||
opt_criterion(109, "(build) preferred providers (non-roots)").
|
||||
opt_criterion(9, "preferred providers (non-roots)").
|
||||
#minimize{ 0@109: #true }.
|
||||
#minimize{ 0@9: #true }.
|
||||
opt_criterion(8, "preferred providers (non-roots)").
|
||||
#minimize{ 0@208: #true }.
|
||||
#minimize{ 0@8: #true }.
|
||||
#minimize{
|
||||
Weight@9+Priority,Provider,Virtual
|
||||
Weight@8+Priority,Provider,Virtual
|
||||
: provider_weight(Provider, Virtual, Weight), not root(Provider),
|
||||
build_priority(Provider, Priority)
|
||||
}.
|
||||
|
||||
% Try to minimize the number of compiler mismatches in the DAG.
|
||||
opt_criterion(108, "(build) compiler mismatches").
|
||||
opt_criterion(8, "compiler mismatches").
|
||||
#minimize{ 0@108: #true }.
|
||||
#minimize{ 0@8: #true }.
|
||||
opt_criterion(7, "compiler mismatches").
|
||||
#minimize{ 0@207: #true }.
|
||||
#minimize{ 0@7: #true }.
|
||||
#minimize{
|
||||
1@8+Priority,Package,Dependency
|
||||
1@7+Priority,Package,Dependency
|
||||
: compiler_mismatch(Package, Dependency),
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
|
||||
% Try to minimize the number of compiler mismatches in the DAG.
|
||||
opt_criterion(107, "(build) OS mismatches").
|
||||
opt_criterion(7, "OS mismatches").
|
||||
#minimize{ 0@107: #true }.
|
||||
#minimize{ 0@7: #true }.
|
||||
opt_criterion(6, "OS mismatches").
|
||||
#minimize{ 0@206: #true }.
|
||||
#minimize{ 0@6: #true }.
|
||||
#minimize{
|
||||
1@7+Priority,Package,Dependency
|
||||
1@6+Priority,Package,Dependency
|
||||
: node_os_mismatch(Package, Dependency),
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
|
||||
opt_criterion(106, "(build) non-preferred OSes").
|
||||
#minimize{ 0@106: #true }.
|
||||
#minimize{ 0@6: #true }.
|
||||
opt_criterion(5, "non-preferred OS's").
|
||||
#minimize{ 0@205: #true }.
|
||||
#minimize{ 0@5: #true }.
|
||||
#minimize{
|
||||
Weight@6+Priority,Package
|
||||
Weight@5+Priority,Package
|
||||
: node_os_weight(Package, Weight),
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
|
||||
% Choose more recent versions for nodes
|
||||
opt_criterion(105, "(build) version badness").
|
||||
opt_criterion(5, "version badness").
|
||||
#minimize{ 0@105: #true }.
|
||||
#minimize{ 0@5: #true }.
|
||||
#minimize{ 0@204: #true }.
|
||||
#minimize{ 0@4: #true }.
|
||||
#minimize{
|
||||
Weight@5+Priority,Package
|
||||
Weight@4+Priority,Package
|
||||
: version_weight(Package, Weight),
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
|
||||
% Try to use preferred compilers
|
||||
opt_criterion(103, "(build) non-preferred compilers").
|
||||
opt_criterion(3, "non-preferred compilers").
|
||||
#minimize{ 0@103: #true }.
|
||||
#minimize{ 0@203: #true }.
|
||||
#minimize{ 0@3: #true }.
|
||||
#minimize{
|
||||
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
|
||||
% to select the preferred target.
|
||||
opt_criterion(102, "(build) target mismatches").
|
||||
opt_criterion(2, "target mismatches").
|
||||
#minimize{ 0@102: #true }.
|
||||
#minimize{ 0@202: #true }.
|
||||
#minimize{ 0@2: #true }.
|
||||
#minimize{
|
||||
1@2+Priority,Package,Dependency
|
||||
@ -962,9 +956,8 @@ opt_criterion(2, "target mismatches").
|
||||
build_priority(Package, Priority)
|
||||
}.
|
||||
|
||||
opt_criterion(101, "(build) non-preferred targets").
|
||||
opt_criterion(1, "non-preferred targets").
|
||||
#minimize{ 0@101: #true }.
|
||||
#minimize{ 0@201: #true }.
|
||||
#minimize{ 0@1: #true }.
|
||||
#minimize{
|
||||
Weight@1+Priority,Package
|
||||
|
Loading…
Reference in New Issue
Block a user