Skip to content

Commit

Permalink
Conditions are now specified at configuration space creation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kerilk committed Nov 3, 2023
1 parent 5058a45 commit 1a78521
Show file tree
Hide file tree
Showing 20 changed files with 398 additions and 415 deletions.
38 changes: 22 additions & 16 deletions bindings/python/cconfigspace/configuration_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
from .rng import Rng
from parglare.parser import Context as PContext

ccs_create_configuration_space = _ccs_get_function("ccs_create_configuration_space", [ct.c_char_p, ct.c_size_t, ct.POINTER(ccs_parameter), ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ccs_configuration_space)])
ccs_create_configuration_space = _ccs_get_function("ccs_create_configuration_space", [ct.c_char_p, ct.c_size_t, ct.POINTER(ccs_parameter), ct.POINTER(ccs_expression), ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ccs_configuration_space)])
ccs_configuration_space_set_rng = _ccs_get_function("ccs_configuration_space_set_rng", [ccs_configuration_space, ccs_rng])
ccs_configuration_space_get_rng = _ccs_get_function("ccs_configuration_space_get_rng", [ccs_configuration_space, ct.POINTER(ccs_rng)])
ccs_configuration_space_set_condition = _ccs_get_function("ccs_configuration_space_set_condition", [ccs_configuration_space, ct.c_size_t, ccs_expression])
ccs_configuration_space_get_condition = _ccs_get_function("ccs_configuration_space_get_condition", [ccs_configuration_space, ct.c_size_t, ct.POINTER(ccs_expression)])
ccs_configuration_space_get_conditions = _ccs_get_function("ccs_configuration_space_get_conditions", [ccs_configuration_space, ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ct.c_size_t)])
ccs_configuration_space_get_forbidden_clause = _ccs_get_function("ccs_configuration_space_get_forbidden_clause", [ccs_configuration_space, ct.c_size_t, ct.POINTER(ccs_expression)])
Expand All @@ -24,23 +23,40 @@

class ConfigurationSpace(Context):
def __init__(self, handle = None, retain = False, auto_release = True,
name = "", parameters = None, forbidden_clauses = None):
name = "", parameters = None, conditions = None, forbidden_clauses = None):
if handle is None:
count = len(parameters)

if forbidden_clauses is not None:
numfc = len(forbidden_clauses)
if numfc > 0:
ctx = dict(zip([x.name for x in parameters], parameters))
fc_expressions = [ parser.parse(fc, context = PContext(extra=ctx)) if isinstance(fc, str) else fc for fc in forbidden_clauses ]
fcv = (ccs_expression * numfc)(*[x.handle.value for x in fc_expressions])
forbidden_clauses = [ parser.parse(fc, context = PContext(extra=ctx)) if isinstance(fc, str) else fc for fc in forbidden_clauses ]
fcv = (ccs_expression * numfc)(*[x.handle.value for x in forbidden_clauses])
else:
fcv = None
else:
numfc = 0
fcv = None

if conditions is not None:
namedict = dict(zip([x.name for x in parameters], parameters))
indexdict = dict(reversed(ele) for ele in enumerate(parameters))
cv = (ccs_expression * count)()
conditions = dict( (k, parser.parse(v, context = PContext(extra=namedict)) if isinstance(v, str) else v) for (k, v) in conditions.items() )
for (k, v) in conditions.items():
if isinstance(k, Parameter):
cv[indexdict[k]] = v.handle.value
elif isinstance(k, str):
cv[indexdict[namedict[k]]] = v.handle.value
else:
cv[k] = v.handle.value
else:
cv = None

parameters = (ccs_parameter * count)(*[x.handle.value for x in parameters])
handle = ccs_configuration_space()
res = ccs_create_configuration_space(str.encode(name), count, parameters, numfc, fcv, ct.byref(handle))
res = ccs_create_configuration_space(str.encode(name), count, parameters, cv, numfc, fcv, ct.byref(handle))
Error.check(res)
super().__init__(handle = handle, retain = False)
else:
Expand All @@ -62,16 +78,6 @@ def rng(self, r):
res = ccs_configuration_space_set_rng(self.handle, r.handle)
Error.check(res)

def set_condition(self, parameter, expression):
if isinstance(expression, str):
expression = parser.parse(expression, context = PContext(extra=self))
if isinstance(parameter, Parameter):
parameter = self.parameter_index(parameter)
elif isinstance(parameter, str):
parameter = self.parameter_index_by_name(parameter)
res = ccs_configuration_space_set_condition(self.handle, parameter, expression.handle)
Error.check(res)

def condition(self, parameter):
if isinstance(parameter, Parameter):
parameter = self.parameter_index(parameter)
Expand Down
3 changes: 3 additions & 0 deletions bindings/python/cconfigspace/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def samples(self, count, distribution = None, rng = None):
def __eq__(self, other):
return self.__class__ == other.__class__ and self.handle.value == other.handle.value

def __hash__(self):
return hash(self.handle.value)


ccs_create_float_numerical_parameter = _ccs_get_function("ccs_create_float_numerical_parameter", [ct.c_char_p, ccs_float, ccs_float, ccs_float, ccs_float, ct.POINTER(ccs_parameter)])
ccs_create_int_numerical_parameter = _ccs_get_function("ccs_create_int_numerical_parameter", [ct.c_char_p, ccs_int, ccs_int, ccs_int, ccs_int, ct.POINTER(ccs_parameter)])
Expand Down
43 changes: 20 additions & 23 deletions bindings/python/test/test_configuration_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,10 @@ def test_conditions(self):
h1 = ccs.NumericalParameter.Float(lower = -1.0, upper = 1.0, default = 0.0)
h2 = ccs.NumericalParameter.Float(lower = -1.0, upper = 1.0)
h3 = ccs.NumericalParameter.Float(lower = -1.0, upper = 1.0)
f1 = ccs.Expression.Less(left = h1, right = 0.0)
cs = ccs.ConfigurationSpace(name = "space", parameters = [h1, h2, h3], forbidden_clauses = [f1])
e1 = ccs.Expression.Less(left = h2, right = 0.0)
cs.set_condition(h3, e1)
e2 = ccs.Expression.Less(left = h3, right = 0.0)
cs.set_condition(h1, e2)
f1 = ccs.Expression.Less(left = h1, right = 0.0)
cs = ccs.ConfigurationSpace(name = "space", parameters = [h1, h2, h3], conditions = {h1: e2, h3: e1}, forbidden_clauses = [f1])
conditions = cs.conditions
conditional_parameters = cs.conditional_parameters
unconditional_parameters = cs.unconditional_parameters
Expand Down Expand Up @@ -145,8 +143,6 @@ def test_omp(self):
forbiddend = ccs.Expression.Equal(left = p3, right = ' ')
forbidden1 = ccs.Expression.And(left = forbiddenc, right = forbiddend)

cs = ccs.ConfigurationSpace(name = "omp", parameters = [p1, p2, p3, p4, p5, p6, p7, p8, p9], forbidden_clauses = [forbidden0, forbidden1])

cond0 = ccs.Expression.Equal(left = p1, right = '#pragma omp #P2')
cond1 = ccs.Expression.Equal(left = p1, right = '#pragma omp target teams distribute #P2')
cond2 = ccs.Expression.Equal(left = p1, right = '#pragma omp target teams distribute #P4')
Expand All @@ -163,14 +159,16 @@ def test_omp(self):

cond10 = ccs.Expression.Equal(left = p6, right = 'numthreads(#P9)')

cs.set_condition(p2, ccs.Expression.Or(left = cond0, right = cond1))
cs.set_condition(p4, cond2)
cs.set_condition(p3, ccs.Expression.Or(left = cond3, right = cond4))
cs.set_condition(p5, cond5)
cs.set_condition(p6, cond6)
cs.set_condition(p7, ccs.Expression.Or(left = cond8, right = cond9))
cs.set_condition(p8, ccs.Expression.Or(left = cond7, right = cond9))
cs.set_condition(p9, cond10)
cs = ccs.ConfigurationSpace(name = "omp", parameters = [p1, p2, p3, p4, p5, p6, p7, p8, p9],
conditions = {p2: ccs.Expression.Or(left = cond0, right = cond1),
p4: cond2,
p3: ccs.Expression.Or(left = cond3, right = cond4),
p5: cond5,
p6: cond6,
p7: ccs.Expression.Or(left = cond8, right = cond9),
p8: ccs.Expression.Or(left = cond7, right = cond9),
p9: cond10},
forbidden_clauses = [forbidden0, forbidden1])

all_params = [ "p{}".format(i) for i in range(1,10) ]
for i in range(1000):
Expand Down Expand Up @@ -233,18 +231,17 @@ def test_omp_parse(self):
values = ['1', '8', '16'])

cs = ccs.ConfigurationSpace(name = "omp", parameters = [p1, p2, p3, p4, p5, p6, p7, p8, p9],
conditions = {p2: "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']",
p4: "p1 == '#pragma omp target teams distribute #P4'",
p3: "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'",
p5: "p2 == 'parallel for #P5'",
p6: "p2 == 'parallel for #P6'",
p7: "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']",
p8: "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'",
p9: "p6 == 'numthreads(#P9)'"},
forbidden_clauses = ["p1 == '#pragma omp #P2' && p2 == ' '",
"p1 == '#pragma omp #P3' && p3 == ' '"])

cs.set_condition(p2, "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']")
cs.set_condition(p4, "p1 == '#pragma omp target teams distribute #P4'")
cs.set_condition(p3, "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'")
cs.set_condition(p5, "p2 == 'parallel for #P5'")
cs.set_condition(p6, "p2 == 'parallel for #P6'")
cs.set_condition(p7, "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']")
cs.set_condition(p8, "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'")
cs.set_condition(p9, "p6 == 'numthreads(#P9)'")

all_params = [ "p{}".format(i) for i in range(1,10) ]
for i in range(1000):
s = cs.sample()
Expand Down
48 changes: 29 additions & 19 deletions bindings/ruby/lib/cconfigspace/configuration_space.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
module CCS
attach_function :ccs_create_configuration_space, [:string, :size_t, :pointer, :size_t, :pointer, :pointer], :ccs_result_t
attach_function :ccs_create_configuration_space, [:string, :size_t, :pointer, :pointer, :size_t, :pointer, :pointer], :ccs_result_t
attach_function :ccs_configuration_space_set_rng, [:ccs_configuration_space_t, :ccs_rng_t], :ccs_result_t
attach_function :ccs_configuration_space_get_rng, [:ccs_configuration_space_t, :pointer], :ccs_result_t
attach_function :ccs_configuration_space_set_condition, [:ccs_configuration_space_t, :size_t, :ccs_expression_t], :ccs_result_t
attach_function :ccs_configuration_space_get_condition, [:ccs_configuration_space_t, :size_t, :pointer], :ccs_result_t
attach_function :ccs_configuration_space_get_conditions, [:ccs_configuration_space_t, :size_t, :pointer, :pointer], :ccs_result_t
attach_function :ccs_configuration_space_get_forbidden_clause, [:ccs_configuration_space_t, :size_t, :pointer], :ccs_result_t
Expand All @@ -16,26 +15,51 @@ module CCS
class ConfigurationSpace < Context

def initialize(handle = nil, retain: false, auto_release: true,
name: "", parameters: nil, forbidden_clauses: nil)
name: "", parameters: nil, conditions: nil, forbidden_clauses: nil)
if handle
super(handle, retain: retain, auto_release: auto_release)
else
count = parameters.size
p_parameters = MemoryPointer::new(:ccs_parameter_t, count)
p_parameters.write_array_of_pointer(parameters.collect(&:handle))
ptr = MemoryPointer::new(:ccs_configuration_space_t)

if forbidden_clauses
ctx = parameters.map { |p| [p.name, p] }.to_h
p = ExpressionParser::new(ctx)
forbidden_clauses = forbidden_clauses.collect { |e| e.kind_of?(String) ? p.parse(e) : e }
fccount = forbidden_clauses.size
fcptr = MemoryPointer::new(:ccs_expression_t, count)
fcptr = MemoryPointer::new(:ccs_expression_t, fccount)
fcptr.write_array_of_pointer(forbidden_clauses.collect(&:handle))
else
fccount = 0
fcptr = nil
end
CCS.error_check CCS.ccs_create_configuration_space(name, count, p_parameters, fccount, fcptr, ptr)

if conditions
ctx = parameters.map { |p| [p.name, p] }.to_h
indexdict = parameters.each_with_index.to_h
p = ExpressionParser::new(ctx)
conditions = conditions.transform_values { |v| v.kind_of?(String) ? p.parse(v) : v }
cond_handles = [0]*count
conditions.each do |k, v|
index = case k
when Parameter
indexdict[k]
when String, Symbol
indexdict[ctx[k]]
else
k
end
cond_handles[index] = v.handle
end
cptr = MemoryPointer::new(:ccs_expression_t, count)
cptr.write_array_of_pointer(cond_handles)
else
cptr = nil
end

CCS.error_check CCS.ccs_create_configuration_space(name, count, p_parameters, cptr, fccount, fcptr, ptr)
super(ptr.read_ccs_configuration_space_t, retain:false)
end
end
Expand All @@ -55,20 +79,6 @@ def rng=(r)
r
end

def set_condition(parameter, expression)
if expression.kind_of? String
expression = ExpressionParser::new(self).parse(expression)
end
case parameter
when Parameter
parameter = parameter_index(parameter);
when String, Symbol
parameter = parameter_index_by_name(parameter);
end
CCS.error_check CCS.ccs_configuration_space_set_condition(@handle, parameter, expression)
self
end

def condition(parameter)
case parameter
when Parameter
Expand Down
47 changes: 22 additions & 25 deletions bindings/ruby/test/test_configuration_space.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,10 @@ def test_conditions
h1 = CCS::NumericalParameter::Float.new(lower: -1.0, upper: 1.0, default: 0.0)
h2 = CCS::NumericalParameter::Float.new(lower: -1.0, upper: 1.0)
h3 = CCS::NumericalParameter::Float.new(lower: -1.0, upper: 1.0)
f1 = CCS::Expression::Less.new(left: h1, right: 0.0)
cs = CCS::ConfigurationSpace::new(name: "space", parameters: [h1, h2, h3], forbidden_clauses: [f1])
e1 = CCS::Expression::Less.new(left: h2, right: 0.0)
cs.set_condition(h3, e1)
e2 = CCS::Expression::Less.new(left: h3, right: 0.0)
cs.set_condition(h1, e2)
f1 = CCS::Expression::Less.new(left: h1, right: 0.0)
cs = CCS::ConfigurationSpace::new(name: "space", parameters: [h1, h2, h3], conditions: {h1 => e2, h3 => e1}, forbidden_clauses: [f1])
conditions = cs.conditions
conditional_parameters = cs.conditional_parameters
unconditional_parameters = cs.unconditional_parameters
Expand Down Expand Up @@ -154,9 +152,6 @@ def test_omp
forbiddend = CCS::Expression::Equal.new(left: p3, right: ' ')
forbidden1 = CCS::Expression::And.new(left: forbiddenc, right: forbiddend)

cs = CCS::ConfigurationSpace::new(name: "omp", parameters: [p1, p2, p3, p4, p5, p6, p7, p8, p9],
forbidden_clauses: [forbidden0, forbidden1])

cond0 = CCS::Expression::Equal.new(left: p1, right: '#pragma omp #P2')
cond1 = CCS::Expression::Equal.new(left: p1, right: '#pragma omp target teams distribute #P2')
cond2 = CCS::Expression::Equal.new(left: p1, right: '#pragma omp target teams distribute #P4')
Expand All @@ -173,15 +168,17 @@ def test_omp

cond10 = CCS::Expression::Equal.new(left: p6, right: 'numthreads(#P9)')

cs.set_condition(p2, CCS::Expression::Or.new(left: cond0, right: cond1))
cs.set_condition(p4, cond2)
cs.set_condition(p3, CCS::Expression::Or.new(left: cond3, right: cond4))
cs.set_condition(p5, cond5)
cs.set_condition(p6, cond6)
cs.set_condition(p7, CCS::Expression::Or.new(left: cond8, right: cond9))
cond_p8 = CCS::Expression::Or.new(left: cond7, right: cond9)
cs.set_condition(p8, cond_p8)
cs.set_condition(p9, cond10)
cs = CCS::ConfigurationSpace::new(name: "omp", parameters: [p1, p2, p3, p4, p5, p6, p7, p8, p9],
conditions: {
p2 => CCS::Expression::Or.new(left: cond0, right: cond1),
p4 => cond2,
p3 => CCS::Expression::Or.new(left: cond3, right: cond4),
p5 => cond5,
p6 => cond6,
p7 => CCS::Expression::Or.new(left: cond8, right: cond9),
p8 => CCS::Expression::Or.new(left: cond7, right: cond9),
p9 => cond10 },
forbidden_clauses: [forbidden0, forbidden1])

all_params = (1..9).collect { |i| "p#{i}" }

Expand Down Expand Up @@ -249,18 +246,18 @@ def test_omp_parse
values: ['1', '8', '16'])

cs = CCS::ConfigurationSpace::new(name: "omp", parameters: [p1, p2, p3, p4, p5, p6, p7, p8, p9],
conditions: {
p2 => "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']",
p4 => "p1 == '#pragma omp target teams distribute #P4'",
p3 => "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'",
p5 => "p2 == 'parallel for #P5'",
p6 => "p2 == 'parallel for #P6'",
p7 => "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']",
p8 => "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'",
p9 => "p6 == 'numthreads(#P9)'" },
forbidden_clauses: ["p1 == '#pragma omp #P2' && p2 == ' '",
"p1 == '#pragma omp #P3' && p3 == ' '"])

cs.set_condition(p2, "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']")
cs.set_condition(p4, "p1 == '#pragma omp target teams distribute #P4'")
cs.set_condition(p3, "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'")
cs.set_condition(p5, "p2 == 'parallel for #P5'")
cs.set_condition(p6, "p2 == 'parallel for #P6'")
cs.set_condition(p7, "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']")
cs.set_condition(p8, "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'")
cs.set_condition(p9, "p6 == 'numthreads(#P9)'")

all_params = (1..9).collect { |i| "p#{i}" }

1000.times {
Expand Down
2 changes: 1 addition & 1 deletion connectors/kokkos/ccs-kokkos-connector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ kokkosp_request_values(

CCS_CHECK(ccs_create_configuration_space(
("cs (region: " + std::to_string(regionCounter) + ")").c_str(),
numTuningVariables, cs_parameters, 0, NULL, &cs));
numTuningVariables, cs_parameters, NULL, 0, NULL, &cs));
delete[] cs_parameters;

#if CCS_DEBUG
Expand Down
Loading

0 comments on commit 1a78521

Please sign in to comment.