Skip to content
Snippets Groups Projects
Commit 5be13d35 authored by Jean-Baptiste Keck's avatar Jean-Baptiste Keck
Browse files

remove graph_tool dependency in favor of networkx

parent 48edf623
No related branches found
No related tags found
1 merge request!16MPI operators
......@@ -7,7 +7,7 @@ from hysop.tools.string_utils import framed_str, strlen, multiline_split
from hysop.tools.numpywrappers import npw
from hysop.core.graph.graph import not_implemented, initialized, discretized, \
ready, graph_built, not_initialized
from hysop.core.graph.graph import Graph, ComputationalGraphNodeData, gt
from hysop.core.graph.graph import ComputationalGraphNodeData
from hysop.core.graph.computational_node import ComputationalGraphNode
from hysop.core.graph.computational_operator import ComputationalGraphOperator
from hysop.core.graph.node_generator import ComputationalGraphNodeGenerator
......@@ -353,16 +353,12 @@ class ComputationalGraph(ComputationalGraphNode):
return u'\n{}\n'.format(framed_str(title=title, msg=ss[1:]))
def variable_report(self):
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
fields = self.fields
topologies = {}
for field in self.fields:
field_topologies = {}
for (i, vid) in enumerate(self.sorted_nodes):
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
for (i, node) in enumerate(self.nodes):
if field in op.input_fields:
topo = op.input_fields[field]
field_topologies.setdefault(topo, []).append(op)
......@@ -420,43 +416,39 @@ class ComputationalGraph(ComputationalGraphNode):
replace = ('--', '', '', '-', '', '')
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
ops = []
for (i, vid) in enumerate(self.sorted_nodes):
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
for (i, node) in enumerate(self.nodes):
handled_inputs, handled_outputs = (), ()
finputs, foutputs = [], []
for f in op.input_tensor_fields:
for f in node.input_tensor_fields:
f0 = f.fields[0]
t0 = op.input_fields[f0]
if all((op.input_fields[fi] is t0) for fi in f.fields):
t0 = node.input_fields[f0]
if all((node.input_fields[fi] is t0) for fi in f.fields):
finputs.append(u'{}.{}'.format(f.pretty_name.decode('utf-8'),
t0.pretty_tag.decode('utf-8')))
handled_inputs += f.fields
for f in op.output_tensor_fields:
for f in node.output_tensor_fields:
f0 = f.fields[0]
t0 = op.output_fields[f0]
if all((op.output_fields[fi] is t0) for fi in f.fields):
t0 = node.output_fields[f0]
if all((node.output_fields[fi] is t0) for fi in f.fields):
foutputs.append(u'{}.{}'.format(f.pretty_name.decode('utf-8'),
t0.pretty_tag.decode('utf-8')))
handled_outputs += f.fields
finputs += [u'{}.{}'.format(f.pretty_name.decode('utf-8'),
t.pretty_tag.decode('utf-8'))
for (f, t) in op.input_fields.iteritems()
for (f, t) in node.input_fields.iteritems()
if f not in handled_inputs]
foutputs += [u'{}.{}'.format(f.pretty_name.decode('utf-8'),
t.pretty_tag.decode('utf-8'))
for (f, t) in op.output_fields.iteritems()
for (f, t) in node.output_fields.iteritems()
if f not in handled_outputs]
finputs = u','.join(sorted(finputs))
foutputs = u','.join(sorted(foutputs))
pinputs = u','.join(sorted([p.pretty_name.decode('utf-8')
for p in op.input_params.values()]))
for p in node.input_params.values()]))
poutputs = u','.join(sorted([p.pretty_name.decode('utf-8')
for p in op.output_params.values()]))
for p in node.output_params.values()]))
infields = u'[{}]'.format(finputs) if finputs else u''
outfields = u'[{}]'.format(foutputs) if foutputs else u''
......@@ -471,8 +463,8 @@ class ComputationalGraph(ComputationalGraphNode):
if outputs == '':
outputs = u'no outputs'
opname = op.pretty_name.decode('utf-8')
optype = type(op).__name__
opname = node.pretty_name.decode('utf-8')
optype = type(node).__name__
strdata = (str(i), opname, inputs, '->', outputs, optype)
ops += multiline_split(strdata, maxlen, split_sep, replace, newline_prefix)
......@@ -626,11 +618,8 @@ class ComputationalGraph(ComputationalGraphNode):
def check(self):
super(ComputationalGraph, self).check()
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
for vid in self.sorted_nodes:
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
op.check()
for node in self.nodes:
node.check()
@debug
def get_field_requirements(self):
......@@ -722,66 +711,16 @@ class ComputationalGraph(ComputationalGraphNode):
from hysop import main_rank
if (visu_rank is None) or (main_rank != visu_rank):
return
graph = self.reduced_graph
edge_text = graph.edge_properties['var_names']
vertex_text = graph.vertex_properties['op_pnames']
vertex_info = graph.vertex_properties['op_info']
if 'command_queues' in graph.vp:
command_queues = graph.vertex_properties['command_queues']
active_ops = graph.vertex_properties['active_ops']
else:
command_queues = None
active_ops = None
def draw():
import time
from gi.repository import Gtk, GObject
from graph_tool.draw import GraphWindow, sfdp_layout
pos_layout = sfdp_layout(graph)
win = GraphWindow(graph, pos_layout, geometry=(800, 600),
vertex_text=vertex_text,
edge_text=edge_text,
vertex_font_size=vertex_font_size,
edge_font_size=edge_font_size,
vertex_color=active_ops,
vertex_fill_color=command_queues,
display_props=vertex_info,
display_props_size=14,
max_render_time=50)
def update_window():
win.graph.regenerate_surface()
win.graph.queue_draw()
time.sleep(0.01)
return True
GObject.idle_add(update_window)
win.connect("delete_event", Gtk.main_quit)
win.show_all()
Gtk.main()
self.graph_is_rendering = False
self.graph_is_rendering = True
from threading import Thread
display_thread = Thread(target=draw)
display_thread.start()
raise NotImplementedError('This feature has not been implemented yet.')
@debug
@graph_built
def discretize(self):
if self.discretized:
return
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
for vid in self.sorted_nodes:
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
if not op.discretized:
op.discretize()
for node in self.nodes:
if not node.discretized:
node.discretize()
if self.is_root:
input_discrete_fields = {}
......@@ -846,14 +785,10 @@ class ComputationalGraph(ComputationalGraphNode):
def get_work_properties(self):
requests = MultipleOperatorMemoryRequests()
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
for vid in self.sorted_nodes:
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
if op not in requests.operators():
wp = op.get_work_properties()
requests += op.get_work_properties()
for node in self.nodes:
if node not in requests.operators():
wp = node.get_work_properties()
requests += node.get_work_properties()
if __DEBUG__ or (__VERBOSE__ and self.level == 0) or self.__FORCE_REPORTS__:
srequests = requests.sreport()
ss = (srequests if (srequests != u'') else u' *no extra work requested*')
......@@ -870,13 +805,9 @@ class ComputationalGraph(ComputationalGraphNode):
if (work is None):
work = self.get_work_properties()
work.allocate(allow_subbuffers=allow_subbuffers)
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
for vid in self.sorted_nodes:
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
if not op.ready:
op.setup(work=work)
for node in self.nodes:
if not node.ready:
node.setup(work=work)
self.ready = True
def build(self, outputs_are_inputs=True, method=None, allow_subbuffers=False):
......@@ -896,38 +827,17 @@ class ComputationalGraph(ComputationalGraphNode):
@debug
@ready
def apply(self, **kwds):
drawing = self.graph_is_rendering
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
if drawing:
active_ops = reduced_graph.vertex_properties['active_ops']
old_color = None
for vid in self.sorted_nodes:
if old_color:
active_ops[vertex] = old_color
vertex = reduced_graph.vertex(vid)
old_color = active_ops[vertex]
active_ops[vertex] = 'red'
op = operators[vertex]
dprint('{}.apply()'.format(op.name))
op.apply(**kwds)
active_ops[vertex] = old_color
else:
for op in self.nodes:
dprint('{}.apply()'.format(op.name))
op.apply(**kwds)
for node in self.nodes:
dprint('{}.apply()'.format(node.name))
node.apply(**kwds)
@debug
@ready
def finalize(self, **kwds):
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
for vid in self.sorted_nodes:
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
if op.ready:
op.finalize(**kwds)
for node in self.nodes:
if node.ready:
node.finalize(**kwds)
self.ready = False
@classmethod
......
import inspect
import graph_tool as gt
from graph_tool import Graph, GraphView
from graph_tool import topology, stats, search
from hysop.tools.decorators import not_implemented, debug, wraps, profile
import inspect, networkx
from hysop import dprint
from hysop.tools.types import check_instance, first_not_None
from hysop.tools.decorators import not_implemented, debug, wraps, profile
is_directed_acyclic_graph = networkx.algorithms.dag.is_directed_acyclic_graph
transitive_reduction = networkx.algorithms.dag.transitive_reduction
def all_simple_paths(graph, src, dst):
return tuple(networkx.algorithms.simple_paths.all_simple_paths(graph, src, dst))
def topological_sort(graph):
return tuple(networkx.algorithms.dag.topological_sort(graph))
def new_directed_graph():
return networkx.DiGraph()
def new_vertex(graph, *args, **kwds):
# /!\ We have to use networkx 2.2 which has a different interface for attributes
node = VertexAttributes(graph, *args, **kwds)
graph.add_node(node)
return node
def new_edge(graph, u, v, *args, **kwds):
# /!\ We have to use networkx 2.2 which has a different interface for attributes
graph.add_edge(u, v, object=EdgeAttributes(*args, **kwds))
return (u,v)
class VertexAttributes(object):
"""Simple class to hold vertex data."""
def __init__(self, graph, operator=None):
if not hasattr(graph, '_hysop_node_counter'):
graph._hysop_node_counter = 0
node_id = graph._hysop_node_counter
graph._hysop_node_counter += 1
self.node_id = node_id
self.operator = operator
self.input_states = None
self.output_states = None
self.op_ordering = None
self.command_queue = None
def copy_attributes(self, other):
if (other is None):
return self
check_instance(other, VertexAttributes)
for vname in ('operator',
'input_states', 'output_states',
'op_ordering', 'command_queue'):
setattr(self, vname, first_not_None(getattr(self, vname),
getattr(other, vname)))
return self
def set_op_info(self, operator, input_states, output_states):
assert (self.operator is not None)
assert self.operator is operator
self.operator = operator
self.input_states = input_states
self.output_states = output_states
return self
def hash(self):
return self.node_id
def __eq__(self, other):
return self.node_id == other.node_id
def __int__(self):
return self.node_id
class EdgeAttributes(object):
"""Simple class to hold edge data."""
def __init__(self, variable=None, topology=None):
self.variable = variable
self.topology = topology
class ComputationalGraphNodeData(object):
"""
Simple class to hold some node data.
......@@ -127,7 +195,6 @@ def op_apply(f):
@profile
@ready
def apply(*args, **kwds):
#print u'APPLY {}'.format(args[0].name)
dbg = ('dbg' in kwds)
dbg = dbg and (kwds['dbg'] is not None)
dbg = dbg and (kwds['dbg'].enable_on_op_apply)
......@@ -175,3 +242,53 @@ def op_apply(f):
return
return ret
return apply
def _op_info(op, istates=None, ostates=None, jmp=False):
ifields = op.input_fields
ofields = op.output_fields
iparams = op.input_params
oparams = op.output_params
memorder2str = {
MemoryOrdering.C_CONTIGUOUS: 'C',
MemoryOrdering.F_CONTIGUOUS: 'F',
}
def ifinfo(field, topo):
info = (field.name, topo.id)
if istates:
assert field in istates
istate = istates[field]
assert (istate is not None)
info+=(memorder2str[istate.memory_order],)
info+=(str(istate.tstate),)
return info
def ofinfo(field, topo):
info = (field.name, topo.id)
if ostates:
assert field in ostates
ostate = ostates[field]
assert (ostate is not None)
info+=(memorder2str[ostate.memory_order],)
info+=(str(ostate.tstate),)
return info
def ipinfo(param):
return param.name
def opinfo(param):
return param.name
ss = 'Operator {} => \n {}{}{}{}\n {}'.format(op.name,
'Pin:{}\n '.format([ ipinfo(param) for param in iparams.values() ])
if iparams else '',
'Fin:{}\n '.format([ ifinfo(f,topo) for (f,topo) in ifields.iteritems() ])
if ifields else '',
'Pout:{}\n '.format([ opinfo(param) for param in oparams.values() ])
if oparams else '',
'Fout:{}\n '.format([ ofinfo(f,topo) for (f,topo) in ofields.iteritems() ])
if ofields else '',
op.__class__)
if jmp:
return ss
else:
return ss.replace('\n',' ')
This diff is collapsed.
......@@ -180,7 +180,7 @@ class TestVorticityAbsorption(object):
dist = npw.abs(fout-fref)
dinf = npw.max(dist)
deps = int(npw.ceil(dinf/eps))
if (deps < 100):
if (deps < 200):
print '{}eps, '.format(deps),
continue
has_nan = npw.any(npw.isnan(fout))
......
......@@ -275,7 +275,7 @@ class TestSpectralDerivative(object):
except OverflowError:
import numpy as np
deps = np.inf
if (deps <= 10**(nidx+2)):
if (deps <= 2*10**(nidx+2)):
if (j == 1):
print '{}eps ({})'.format(deps, dinf),
else:
......
......@@ -81,13 +81,8 @@ class Problem(ComputationalGraph):
self.check_unique_clenv()
def check_unique_clenv(self):
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
cl_env, op = None, None
for vid in self.sorted_nodes:
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
cl_env, first_op = None, None
for op in self.nodes:
for topo in set(op.input_fields.values() + op.output_fields.values()):
if (topo.backend.kind == Backend.OPENCL):
if (cl_env is None):
......@@ -105,13 +100,8 @@ class Problem(ComputationalGraph):
def initialize_field(self, field, **kwds):
"""Initialize a field on all its input and output topologies."""
reduced_graph = self.reduced_graph
operators = reduced_graph.vertex_properties['operators']
initialized = set()
for vid in self.sorted_nodes:
vertex = reduced_graph.vertex(vid)
op = operators[vertex]
for op in self.nodes:
# give priority to tensor field initialization
for op_fields in (self.input_discrete_tensor_fields, self.output_discrete_tensor_fields,
op.input_discrete_tensor_fields, op.output_discrete_tensor_fields,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment