diff --git a/.gitignore b/.gitignore index ce5c01ab14cc7e2685eaace19a57fd29780c90e6..bc88d7251ca2fe421373c81e2cadb4b157fe225c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ **/__binaries__ /openmp **/__pycache__ -*.pyc +*.py[co] diff --git a/__init__.py b/__init__.py index 0bca79607d08fbcad7a4ec756e380a1da1dd782d..01d84d95d4c3fe2b57d68dbd5c6706589ab2b121 100644 --- a/__init__.py +++ b/__init__.py @@ -21,8 +21,8 @@ try: assert "built-in" in str(gdb.breakpoints) # make sure we have the right gdb package except Exception as e: import importlib - if not ("No module named" in str(e) and "gdb" in str(e)) and \ - not ("module 'gdb' has no attribute 'breakpoints'" in str(e)): + if (not ("No module named" in str(e) and "gdb" in str(e)) and + not ("module 'gdb' has no attribute 'breakpoints'" in str(e))): log.error("Cannot import gdb: {}".format(e)) log.critical("Importing DUMMY gdb module") @@ -44,8 +44,13 @@ from .toolbox.python_utils import internal, info from .toolbox import register_model, toggle_activate_submodules log.info("Loading mcgdb models ...") -from . import model - +try: + from . import model +except Exception as e: + log_user.fatal("### ###") + log_user.fatal("### Loading mcgdb models failed. ###") + log_user.fatal("### ###") + log_user.exception(e) log_user.info("Loading of mcgdb environment completed.") ################### @@ -56,8 +61,8 @@ def initialize_by_name(): gdb_binname = line.split("\x00")[0] if "mcgdb" not in gdb_binname: - log.warn("*Not* loading mcgdb debugging extention.") - log.warn("Run `py import mcgdb; mcgdb.initialize()` to load it manually.") + log_user.warn("*Not* loading mcgdb debugging extention.") + log_user.warn("Run `py import mcgdb; mcgdb.initialize()` to load it manually.") return initialize() diff --git a/capture.py b/capture.py index 82d4b1ac58c48acfa77b23c71b9f8f50448fe98d..f1d72f4b7fc62a6b8ae4357b689b955e22f8d4fc 100644 --- a/capture.py +++ b/capture.py @@ -305,7 +305,8 @@ class FunctionBreakpoint(gdb.Breakpoint, representation.Filterable): ret = None mcgdb.toolbox.callback_crash("FunctionBreakpoint.prepare_before", e) - if ret is None: return False #spurious stop + if ret is None: #spurious stop + return interaction.proceed_stop_requests() (fct_stop, fct_finish, fct_data) = ret diff --git a/interaction/aspect.py b/interaction/aspect.py index 4dd97732e73cd1e1a6a6df4ed9539aab79b1be28..0a6bdb1da4840c1264c8c3abb29b6d01a504f908 100644 --- a/interaction/aspect.py +++ b/interaction/aspect.py @@ -18,7 +18,7 @@ class cmd_aspect_remove(gdb.Command): gdb.Command.__init__ (self, "mcgdb aspects remove", gdb.COMMAND_NONE) def invoke (self, argv, from_tty): - if "all" == argv: + if argv.startswith("all"): aspect.registered_trackers.clear() print("All aspects removed.") return diff --git a/interaction/my_gdb.py b/interaction/my_gdb.py index 05d0c33d346c4d1bb4f2524a3852b7a7c3c80886..cfadcaeab841b5594f461e8c3e8b43ef17497cb2 100644 --- a/interaction/my_gdb.py +++ b/interaction/my_gdb.py @@ -214,7 +214,16 @@ class cmd_mcgdb_load_by_name(gdb.Command): def invoke (self, args, from_tty): toolbox.load_models_by_name(args) - + +class cmd_mcgdb_load_by_library(gdb.Command): + def __init__(self): + gdb.Command.__init__ (self, "mcgdb load_model_by_libname", gdb.COMMAND_NONE) + + def invoke (self, args, from_tty): + class objfile: + filename = args + toolbox.detect_models(objfile) + class cmd_mcgdb_detect(gdb.Command): def __init__(self): gdb.Command.__init__ (self, "mcgdb detect_models", gdb.COMMAND_NONE) @@ -280,6 +289,7 @@ def postInitialize(): cmd_mcgdb_autodetect() cmd_mcgdb_detect() cmd_mcgdb_load_by_name() + cmd_mcgdb_load_by_library() gdb.events.cont.connect(cont) diff --git a/model/__init__.py b/model/__init__.py index 286095f01540d33999d845cfbde62b68dfadaa87..5891cdd4cb866044432f9f1f2effe83af2628f26 100644 --- a/model/__init__.py +++ b/model/__init__.py @@ -1,138 +1,2 @@ -from . import gpu, task, profiling, aftermath +from . import gpu, task, profiling, numa - -import gdb -import mcgdb -from mcgdb.toolbox.target import my_archi -from mcgdb.toolbox import my_gdb - -# class kmpc_barrier_Breakpoint(mcgdb.capture.FunctionBreakpoint): -# func_type = mcgdb.capture.FunctionTypes.conf_func - -# def __init__(self): -# mcgdb.capture.FunctionBreakpoint.__init__(self, "__kmpc_for_static_init_4") - -# def prepare_before (self): -# data = {} -# data["lower"] = my_archi.nth_arg(5, my_archi.INT_P) -# data["upper"] = my_archi.nth_arg(6, my_archi.INT_P) - -# return (False, True, data) - -# def prepare_after (self, data): -# lower, upper = data["lower"].dereference(), data["upper"].dereference() - -# if lower == 84: -# print("ITER FAST to 86: {} -- {}".format(lower, upper)) -# return True -# if lower == 312: -# print("ITER SLOW to 314: {} -- {}".format(lower, upper)) -# return True - -# class cmd_do_break (gdb.Command): -# def __init__ (self): -# gdb.Command.__init__ (self, "do_break", gdb.COMMAND_NONE) - -# def invoke (self, args, from_tty): -# kmpc_barrier_Breakpoint() -# print("Breakpoint set on slow and fast iterations") - -# cmd_do_break() - -# class cmd_do_measure (gdb.Command): -# def __init__ (self): -# gdb.Command.__init__ (self, "do_measure", gdb.COMMAND_NONE) - -# def invoke (self, args, from_tty): -# gdb.execute("set scheduler-locking on") -# gdb.execute("tbreak __kmpc_for_static_fini") -# gdb.execute("profile manual start") -# gdb.execute("cont") -# gdb.execute("profile manual stop") -# gdb.execute("set scheduler-locking off") -# cmd_do_break() -# cmd_do_measure() - -import mcgdb.interaction - -class kmpc_for_static_Breakpoint(mcgdb.capture.FunctionBreakpoint): - func_type = mcgdb.capture.FunctionTypes.conf_func - - def __init__(self): - mcgdb.capture.FunctionBreakpoint.__init__(self, "__kmpc_for_static_init_4") - def prepare_before (self): - data = {} - data["lower"] = my_archi.nth_arg(5, my_archi.INT_P) - data["upper"] = my_archi.nth_arg(6, my_archi.INT_P) - - return (False, True, data) - - def prepare_after (self, data): - lower, upper = data["lower"].dereference(), data["upper"].dereference() #spurious stop - print("Execute loop {} == {}".format(lower, upper)) - - gdb.execute("set scheduler-locking on") - gdb.execute("profile manual start") - -total = None -hits = 0 -has_hit = False -class kmpc_for_fini_Breakpoint(mcgdb.capture.FunctionBreakpoint): - func_type = mcgdb.capture.FunctionTypes.conf_func - - def __init__(self): - mcgdb.capture.FunctionBreakpoint.__init__(self, "__kmpc_for_static_fini") - - def prepare_before (self): - gdb.execute("profile manual stop") - gdb.execute("set scheduler-locking off") - - global hits - hits += 1 - - do_stop = hits == total - if do_stop: - print("FINISHED") - - if has_hit: - do_stop = True - has_hit = False - - if mcgdb.interaction.stop_requests: - print("---> {}".format(mcgdb.interaction.stop_requests)) - global has_hit - has_hit = True - - return do_stop, False, {} - -class cmd_measure_all(gdb.Command): - def __init__ (self): - gdb.Command.__init__ (self, "measure_all", gdb.COMMAND_NONE) - - def invoke (self, args, from_tty): - kmpc_for_static_Breakpoint() - kmpc_for_fini_Breakpoint() - global total - total = len(gdb.selected_inferior().threads()) - -cmd_measure_all() - -import os -class cmd_pagemap(gdb.Command): - def __init__ (self): - gdb.Command.__init__ (self, "pagemap", gdb.COMMAND_NONE) - def invoke (self, args, from_tty): - addr = gdb.parse_and_eval(args) - os.system("/home/videau/pagemap -n {} {}".format(gdb.selected_inferior().pid, addr)) - -cmd_pagemap() - - -class cmd_current_numa_node(gdb.Command): - def __init__ (self): - gdb.Command.__init__ (self, "current_numa_node", gdb.COMMAND_NONE) - - def invoke (self, args, from_tty): - with my_gdb.set_parameter("scheduler-locking", "on"): - gdb.execute("p numa_node_of_cpu(sched_getcpu())") -cmd_current_numa_node() diff --git a/model/numa/__init__.py b/model/numa/__init__.py index 45ac7d8f05357a6912b44f5b2735e166f91b9703..07a9fd14609f72f55186c0ff3f531e4afbc9eafc 100644 --- a/model/numa/__init__.py +++ b/model/numa/__init__.py @@ -7,13 +7,14 @@ import logging; log = logging.getLogger(__name__) log_user = logging.getLogger("mcgdb.log.user.numa") import os +import subprocess try: import shutil except ImportError: shutil = None -numa_loaded = False +numa_loaded = None PAGEMAP_PATH = "/home/videau/" PAGEMAP = "pagemap" @@ -22,14 +23,22 @@ pagemap_bin = None class cmd_numa_pagemap(gdb.Command): def __init__ (self): - gdb.Command.__init__ (self, "pagemap", gdb.COMMAND_NONE) + gdb.Command.__init__ (self, "numa pagemap", gdb.COMMAND_NONE) global pagemap_bin - pagemap_bin = PAGEMAP - - if (shutil and shutil.which(PAGEMAP) # > py3.3 - or "/{}".format(PAGEMAP) in os.system("which {}").format(PAGEMAP))): - # nothing to do, we found it - else: + + has_pagepage = False + try: + has_pagepage = shutil.which(PAGEMAP) is not None # > py3.3 + except AttributeError: # py2: shutil doesn't have which + pass + + if not has_pagepage: + try: + has_pagepage = "/{}".format(PAGEMAP) in subprocess.check_output("which {}".format(PAGEMAP), shell=True, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: # which returned false + pass + + if not has_pagepage: pagemap_path = os.path.join(PAGEMAP_PATH, PAGEMAP) if not os.path.isfile(pagemap_path): @@ -39,9 +48,21 @@ class cmd_numa_pagemap(gdb.Command): pagemap_bin = pagemap_path def invoke (self, args, from_tty): - addr = gdb.parse_and_eval(args) - os.system("{} -n {} {}".format(pagemap_bin, gdb.selected_inferior().pid, addr)) + try: + addr = gdb.parse_and_eval(args) + except gdb.error as e: + log_user.error("Cannot evaluate '{}': {}".format(args, e)) + return + + cmd = "{} -n {} {}".format(pagemap_bin, gdb.selected_inferior().pid, addr) + res = subprocess.check_output(cmd, shell=True) + try: + pm_addr, _, node = res[:-1].split(" ") + log_user.info("Address 0x{} is located on node {}".format(pm_addr, node)) + except ValueError: # couldnt split correctly + log_user.warn("Unexpected response from pagemap: '{}'".format(res[:-1])) + class cmd_numa_current_node(gdb.Command): def __init__ (self): gdb.Command.__init__ (self, "numa current_node", gdb.COMMAND_NONE) @@ -49,12 +70,13 @@ class cmd_numa_current_node(gdb.Command): def invoke (self, args, from_tty): for symb in ("numa_node_of_cpu", "sched_getcpu"): if not gdb.lookup_symbol(symb): - log_user.error("Symbol '{}' not found, cannot get current node.".format(symb) - return + log_user.error("Symbol '{}' not found, cannot get current node.".format(symb)) + return with my_gdb.set_parameter("scheduler-locking", "on"): - gdb.execute("p numa_node_of_cpu(sched_getcpu())") - + node = gdb.execute("p numa_node_of_cpu(sched_getcpu())", to_string=True) + node = int(node.partition("= ")[-1]) + log_user.info("Current node is N{}".format(node)) class cmd_numa(gdb.Command): def __init__(self, limited=False): @@ -69,7 +91,7 @@ class cmd_numa(gdb.Command): on_activated() numa_loaded = True - + log_user.info("Numa module successfully loaded.") if args: gdb.execute("numa {}".format(args)) diff --git a/model/profiling/info/__init__.py b/model/profiling/info/__init__.py index c5516cb255f4592efe0bd18e61b13ac41227231e..90beb366e4d67d505ee159366a46d1f11b6496a6 100644 --- a/model/profiling/info/__init__.py +++ b/model/profiling/info/__init__.py @@ -6,7 +6,7 @@ log_user = logging.getLogger("mcgdb.log.user") from mcgdb.toolbox import my_gdb # will be added to global scope -info_counters = "proc", "hit", "counter", "perf", "gprof", "memleaks" +info_counters = "perf_standalone", "omp" #"proc", "hit", "counter", "perf", "gprof", "memleaks" info_counter_classes = None # will be populated in initialize() disabled_counters = set() @@ -26,6 +26,14 @@ class Info_set(list): for info in self: info.stop() + def get(self, key): + values = [] + for info in self: + try: + values.append(info.results[key]) + except KeyError: pass + return values + def new_infoset(): counters = [] for info_counter_class in info_counter_classes: diff --git a/model/profiling/info/perf.py b/model/profiling/info/perf.py index 62aba86c2dd6f08acfa054c2059b7b3da1f5e955..bdbe056850e442e274ad3020b10c2ea26f42faf9 100644 --- a/model/profiling/info/perf.py +++ b/model/profiling/info/perf.py @@ -14,6 +14,11 @@ from .. import capture MCGDB_PATH = "/home/kevin/travail/Python/mcgdb" PREF_LD_PRELOAD = MCGDB_PATH+ "/model/profiling/__binaries__/libmcgdb_perf_stat.preload.so" +try: # Python 3 standard library. + ProcessLookupError +except NameError: # No such class in Python 2. + ProcessLookupError = NotImplemented + class perf_process(): UNITS = {"task-clock": "msec"} @@ -57,6 +62,7 @@ class perf_process(): log.error("Attach perf to process {}".format(pid)) command = ['perf', 'stat', '-x;', #'--pre', "kill -USR1 {}".format(os.getpid()), + '-e', profile.interaction.counters.param_perf_counters.get(), '-p', str(pid), #'sleep', '999999999' # otherwise pref stat --pre returns immediatly ] @@ -297,8 +303,9 @@ class perf_info_ldpreload(): return results def initialize(): - capture.exec_at_main.append(perf_process.launch) - capture.exec_at_exit.append(perf_process.kill) - capture.exec_on_exited.append(perf_process.kill) + #capture.exec_at_main.append(perf_process.launch) + #capture.exec_at_exit.append(perf_process.kill) + #capture.exec_on_exited.append(perf_process.kill) + pass -__COUNTERS__ = [perf_info_ldpreload] +__COUNTERS__ = [] # perf_info_ldpreload diff --git a/model/profiling/info/perf_standalone.py b/model/profiling/info/perf_standalone.py index 7989990f4b41112ec621c474432dd2d2d703c944..dba3ef9baf846e8ad95fe660dfd67a22346836b0 100644 --- a/model/profiling/info/perf_standalone.py +++ b/model/profiling/info/perf_standalone.py @@ -1,6 +1,26 @@ +import subprocess +import signal +import time +from collections import defaultdict, OrderedDict + +import logging; log = logging.getLogger(__name__) +log_user = logging.getLogger("mcgdb.log.user") + +import gdb + +from ..interaction import counters + +DISABLE_STARTUP_SYNC = False +MAX_WAIT = 5 # in 1/10 s +HAS_PERF_SIGNAL = False # need to test version + +if DISABLE_STARTUP_SYNC: + log.warn("No startup sync between perf and mcgdb") + class perf_info_standalone(): "perf stat counters (standalone)" name = "perf standalone" + UNITS = {"task-clock": "msec"} def __init__(self): self.perf = None @@ -11,39 +31,45 @@ class perf_info_standalone(): assert self.perf is None self.rcvd = False - def handler(signum, frame): + + if DISABLE_STARTUP_SYNC: self.rcvd = True + else: + def handler(signum, frame): + self.rcvd = True - import signal, time, os - old = signal.signal(signal.SIGUSR1, handler) - + import signal, time, os + old = signal.signal(signal.SIGUSR1, handler) + command = ['perf', 'stat', '-x,', - '--pre', "kill -USR1 {}".format(os.getpid()), - '-p', str(gdb.selected_inferior().pid), - 'sleep', '999999999' # otherwise pref stat --pre returns immediatly + '-e', counters.param_perf_counters.get() ] - self.perf = subprocess.Popen(command, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + if HAS_PERF_SIGNAL: + # not working with old versions of perf + command += ['--pre', "kill -USR1 {}".format(os.getpid())] + command += [ #'-p', str(gdb.selected_inferior().pid), + '-p', str(gdb.selected_thread().ptid[1]), + 'sleep', '999999999' # otherwise pref stat --pre returns immediatly + ] + self.perf = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.res = "running" assert self.perf.pid > 1 - MAX_WAIT = 100 - cnt = MAX_WAIT - for cnt in range(MAX_WAIT): - if self.rcvd: break - time.sleep(0.1) + if not DISABLE_STARTUP_SYNC: + cnt = MAX_WAIT + for cnt in range(MAX_WAIT): + if self.rcvd: break + time.sleep(0.1) - signal.signal(signal.SIGUSR1, old) + signal.signal(signal.SIGUSR1, old) - if not self.rcvd: - #log.error("Waited to long for perf ...") - pass + if not self.rcvd and HAS_PERF_SIGNAL: + #log.error("Waited to long for perf ...") + pass def stop(self): assert not self.perf.returncode - - #self.perf.send_signal(signal.SIGINT) - sleep_pid = subprocess.Popen(["pgrep", "-P", str(self.perf.pid)], stdout=subprocess.PIPE).stdout.read().decode('ascii') subprocess.Popen(["kill", "-INT", sleep_pid[:-1]], @@ -62,7 +88,8 @@ class perf_info_standalone(): try: self.results[k] += v except TypeError: - #log.error("Cannot add '{}' to '{}'.".format(v, self.results[k])) + log.error("Cannot add '{}' to '{}'.".format(v, self.results[k])) + import pdb;pdb.set_trace() self.results[k] = "{}/{}".format(self.results[k], v) def reset(self): @@ -84,7 +111,7 @@ class perf_info_standalone(): info = OrderedDict() for k, val in self.results.items(): try: - details = perf_info.UNITS[k] + details = perf_info_standalone.UNITS[k] except KeyError: details = "" @@ -101,15 +128,30 @@ class perf_info_standalone(): if "sleep" in line: log.critical("is this line really expected? {}".format(line)) try: - val, _1, desc, _2, pct = line.split(",") - line = None if val == '<not counted>' \ - else float(val) #, "({}% -- {} -- {})".format(pct, _1, _2) + line_split = line.split(",") + if len(line_split) == 2: + # old perf versions + val, desc = line_split + else: + # new versions + val, _1, desc, _2, pct = line_split + + if val == '<not counted>': + line = None + elif "." in val: + val = float(val) + elif val.isdigit(): + val = int(val) + else: + pass + except Exception as e: + import pdb;pdb.set_trace() desc = line - line = str(e) #, "" + val = str(e) #, "" - results[desc] = line + results[desc] = val return results -__COUNTERS__ = [] +__COUNTERS__ = [perf_info_standalone] diff --git a/model/profiling/interaction/__init__.py b/model/profiling/interaction/__init__.py index 78ee3e65a03190d5ea9ff8ea19f3826fcbe34018..e8c96535704215a4e866363ff2481d94f304b51c 100644 --- a/model/profiling/interaction/__init__.py +++ b/model/profiling/interaction/__init__.py @@ -3,7 +3,8 @@ log_user = logging.getLogger("mcgdb.log.user") import gdb -from . import graph, manual, info, manage, profile, summary, graph_offline +from . import graph, manual, info, manage, profile, summary, break_if +from . import counters, graph_offline def initialize(): gdb.Command("profile", gdb.COMMAND_OBSCURE, prefix=True) diff --git a/model/profiling/interaction/break_if.py b/model/profiling/interaction/break_if.py new file mode 100644 index 0000000000000000000000000000000000000000..b1e600959224cdbd8887c055b4b5b8a24653c989 --- /dev/null +++ b/model/profiling/interaction/break_if.py @@ -0,0 +1,49 @@ +import logging; log = logging.getLogger(__name__) +log_user = logging.getLogger("mcgdb.log.user") + +import gdb +from mcgdb.toolbox import my_gdb +profile = None # resolved in initialize() + +class cmd_profile_break (gdb.Command): + def __init__ (self): + gdb.Command.__init__(self, "profile break", gdb.COMMAND_OBSCURE, prefix=True) + + def invoke (self, args, from_tty): + if args == "clear": + profile.Profile.breakpoints[:] = [] + + log_user.info("Profiling breakpoints cleared") + return + elif args.startswith("del"): + log_user.warn("Not implemented yet ...") + return + elif not args: + for i, (cpt, cmpt, val) in enumerate(profile.Profile.breakpoints): + print("#{} {} {} {}".format(i, cpt, cmpt, val)) + return + +class cmd_profile_break_if (gdb.Command): + def __init__ (self): + gdb.Command.__init__(self, "profile break if", gdb.COMMAND_OBSCURE) + + def invoke (self, args, from_tty): + try: + cpt, cmpt, val = args.split(" ") + val = float(val) if "." in val else int(val) + assert cmpt in ("==", "<", ">") + except ValueError: + log.warn("Argument format invalid. Expected '<cpt name> <comparator> <value>'") + return + + profile.Profile.breakpoints.append((cpt, cmpt, val)) + + log_user.info("Profiling breakpoint set on {}.".format(args)) + +@my_gdb.internal +def initialize(): + global profile + from .. import profile + + cmd_profile_break() + cmd_profile_break_if() diff --git a/model/profiling/interaction/counters.py b/model/profiling/interaction/counters.py new file mode 100644 index 0000000000000000000000000000000000000000..78c8b6fd5e9c6d301de90414c175935ca540eb78 --- /dev/null +++ b/model/profiling/interaction/counters.py @@ -0,0 +1,30 @@ +import gdb + +DEFAULT = "instructions,cycles,task-clock" +class param_perf_counters(gdb.Parameter): + __self = None + + @classmethod + def get(clazz): + try: + return clazz.__self.value + except ValueError: + # not initialized + return DEFAULT + + def __init__ (self): + gdb.Parameter.__init__(self, "profile-perf-counters", + gdb.COMMAND_OBSCURE, + gdb.PARAM_STRING) + self.value = DEFAULT + assert param_perf_counters.__self is None + param_perf_counters.__self = self + + def get_set_string(self): + return "perf profiling counters set to '{}'".format(self.value) + + def get_show_string (self, svalue): + return "perf profiling counters are '{}'".format(svalue) + +def initialize(): + param_perf_counters() diff --git a/model/profiling/interaction/graph.py b/model/profiling/interaction/graph.py index e0bf032c3d38e5e226f545330924311179028458..4d6de6b9a06eb20690fa39efc443aaa54efb69ee 100644 --- a/model/profiling/interaction/graph.py +++ b/model/profiling/interaction/graph.py @@ -289,3 +289,55 @@ def initialize(): from .. import profile cmd_profile_graph() + cmd_profile_offline_graph() + +class cmd_profile_offline_graph(gdb.Command): + def __init__ (self): + gdb.Command.__init__(self, "profile graph offline", gdb.COMMAND_OBSCURE, prefix=True) + + def invoke (self, args, from_tty): + import pygal + + import fileinput + + chart = pygal.Line() + names = [] + do_div = False + + finput = fileinput.input() + for line in finput: + line = line[:-1] + + if not line: + finput.close() + break + + if line.endswith(" y2"): + secondary = True + line = line.replace(" y2", "") + elif line.endswith(" /"): + do_div = True + line = line.replace(" /", "") + else: + secondary = False + + try: + name, values = line.split(" | ") + + cast = float if "." in values else int + values = list(map(cast, values.split(" "))) + except Exception as e: + log_user.warn("Parsing failed, the line above will be ignored ({})".format(e)) + continue + if do_div is True: + do_div = values + continue + elif do_div: + values = [a/b for a, b in zip(values, do_div)] + + chart.add(name, values, secondary=secondary) + names.append(name) + + TARGET = '/tmp/chart.png' + chart.render_to_png(TARGET) + log_user.info("Chart of {} plotted into {}".format("/".join(names), TARGET)) diff --git a/model/profiling/interaction/summary.py b/model/profiling/interaction/summary.py index 7d6c6abd57952a55b2483a72317c6a076fa53f96..b0464421a7477becaa0102306b9f7fcfc13f6a9d 100644 --- a/model/profiling/interaction/summary.py +++ b/model/profiling/interaction/summary.py @@ -129,9 +129,18 @@ class cmd_profile_info (gdb.Command): log_user.info("***") def print_a_set(info_set): + MAX_VALUE_LEN = 10 + res = OrderedDict() for info in info_set: - res.update(info.to_log(ongoing)) + results = info.to_log(ongoing) + if results is False: + continue + res.update(results) + + if not res: + log_user.info("EMPTY") + return max_len = max(len(k) for k in res) for k, v in res.items(): @@ -146,15 +155,17 @@ class cmd_profile_info (gdb.Command): str_val = commify(value) else: str_val = str(value) + + padding_value = (MAX_VALUE_LEN - len(str_val.partition(".")[0])) * " " if isinstance(value, Unit): - str_val += value.unit + str_val += " " + value.unit if details: str_val += " ({})".format(details) - padding = (max_len - len(k)) * " " - log_user.info("".join([k, ": ", padding, str_val])) + padding_label = (max_len - len(k)) * " " + log_user.info("".join([k, ": ", padding_label, padding_value, str_val])) if prof.do_first_last and firstlast: log_user.info("first start last stop") @@ -214,16 +225,18 @@ class InfoEntrySummary(): def avg(self, value, prof): if isinstance(value, str): return + try: - prev, it = self.values["avg"] + (prev, _what_), it = self.values["avg"] it += 1 - # iterative mean http://www.heikohoffmann.de/htmlthesis/node134.html - new = + float(value) - prev + prev/it + # iterative mean http://www.heikohoffmann.de/htmlthesis/node134.html + new = prev + float(value) - prev*1/it except KeyError: # first pass new = value it = 0 - except: + except Exception as e: import pdb;pdb.set_trace() + return self.values["avg"] = new, it class cmd_profile_summ (gdb.Command): diff --git a/model/profiling/profile.py b/model/profiling/profile.py index 95b65d813386365d73552a03883747fff2bdedda..2bd95c15de98d7d37e0b9b66fbabf4977e298847 100644 --- a/model/profiling/profile.py +++ b/model/profiling/profile.py @@ -6,6 +6,7 @@ log_user = logging.getLogger("mcgdb.log.user") import gdb import mcgdb +import mcgdb.interaction from mcgdb.toolbox import my_gdb from . import capture, info, interaction, checkpoint @@ -44,7 +45,8 @@ class Profile_info(): @my_gdb.Numbered class Profile(): profiles = [] - + breakpoints = [] + @classmethod def instanciate_info(clazz): return info.new_infoset() @@ -136,9 +138,23 @@ class Profile(): def firstlast(): if self.per_thread.inside >= 1: return - - self.per_thread.firstlast.stop() + + infoset = self.per_thread.firstlast + infoset.stop() + + def need_to_stop(): + + for cpt, cmpt, val in Profile.breakpoints: + for res in infoset.get(cpt): + if any([cmpt == "==" and res == val, + cmpt == ">" and res > val, + cmpt == "<" and res < val]): return cpt, cmpt, val + stop = need_to_stop() + if stop: + log_user.warn("Profiling breakpoint: Found {}".format(" ".join(map(str,stop)))) + mcgdb.interaction.push_stop_request() + def per_fct(): info_set = self.per_thread.per_fct_stack.pop() diff --git a/model/task/environment/openmp/capture/__init__.py b/model/task/environment/openmp/capture/__init__.py index 979bc789310555a1d722695e6e11699b20b5cf58..97098f4f5acb86b1d91da771deed81a49729c2d3 100644 --- a/model/task/environment/openmp/capture/__init__.py +++ b/model/task/environment/openmp/capture/__init__.py @@ -94,8 +94,12 @@ class OmpFramePragma(mcgdb.capture.FrameStripperDecorator): return "#pragma omp {}".format(fct[len(PREFIX):]) + class OmpFunctionBreakpoint(mcgdb.capture.FunctionBreakpoint): + breakpoint_sets = defaultdict(list) + decorator = OmpFramePragma + omp_set = None def __init__(self, spec): try: @@ -112,6 +116,14 @@ class OmpFunctionBreakpoint(mcgdb.capture.FunctionBreakpoint): spec = "iomp_preload.c:"+spec mcgdb.capture.FunctionBreakpoint.__init__(self, spec) + + setname = self.__class__.omp_set + if setname is not None: + # if breakpoint is part of an enable-able set, disable it for now + + # try to slit based on spaces ? + OmpFunctionBreakpoint.breakpoint_sets[setname].append(self) + self.enabled = False class OmpGeneratedFrame(mcgdb.capture.FrameStripperDecorator): def __init__(self, parent): diff --git a/model/task/environment/openmp/capture/gomp/GOMP_barrier.py b/model/task/environment/openmp/capture/gomp/GOMP_barrier.py index 7a56a70278124560a3a300a43ac00c6c44b1aee5..30b7ae594300bf61f00039f30f513b87f9555cad 100644 --- a/model/task/environment/openmp/capture/gomp/GOMP_barrier.py +++ b/model/task/environment/openmp/capture/gomp/GOMP_barrier.py @@ -19,6 +19,7 @@ def filename_lineno(): class GOMP_barrier_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "barrier" def __init__(self): OmpFunctionBreakpoint.__init__(self, "GOMP_barrier") diff --git a/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py b/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py index 9ece83a6586eac17a860689f5389143a3c149506..780cd0ceea61933e22bb6b3f749269f3f045665d 100644 --- a/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py +++ b/model/task/environment/openmp/capture/gomp/GOMP_critical_start_end.py @@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint class GOMP_critical_start_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "critical" def __init__(self, named=False): OmpFunctionBreakpoint.__init__(self, "GOMP_critical_{}start".format("name_" if named else "")) @@ -35,6 +36,7 @@ class GOMP_critical_start_Breakpoint(OmpFunctionBreakpoint): class GOMP_critical_end_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "critical" def __init__(self, named=False): OmpFunctionBreakpoint.__init__(self, "GOMP_critical_{}end".format("name_" if named else "")) diff --git a/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py b/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py index f4f675e0a85f8948c20212861e45890b484f1d23..58516876c6caf4d6751877602fff3e7f07bb547c 100644 --- a/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py +++ b/model/task/environment/openmp/capture/gomp/GOMP_parallel_start_end.py @@ -14,6 +14,7 @@ from .. import OmpFunctionBreakpoint, omp_fct_to_job, get_omp_zone class GOMP_parallel_start_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func inner_breakpoint = {} + omp_set = "parallel" def __init__(self, section=False, parallel=False): if section: @@ -68,6 +69,7 @@ class GOMP_parallel_start_Breakpoint(OmpFunctionBreakpoint): class GOMP_parallel_end_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "parallel" def __init__(self): OmpFunctionBreakpoint.__init__(self, "GOMP_parallel_end") @@ -89,7 +91,8 @@ class GOMP_parallel_end_Breakpoint(OmpFunctionBreakpoint): class GOMP_parallel_function_Breakpoint(mcgdb.capture.FunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "parallel" + def __init__(self, fn, job, creator): addr = "*"+str(fn).split(" ")[0] mcgdb.capture.FunctionBreakpoint.__init__(self, addr) diff --git a/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py b/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py index f5d8132a6fc67261e626a2de3be3c8646a64deb1..6365d4152a60bdc91920ee7d417575eea8836f1a 100644 --- a/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py +++ b/model/task/environment/openmp/capture/gomp/GOMP_sections_next.py @@ -11,7 +11,8 @@ from . import GOMP_parallel_start_end class GOMP_sections_start_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "sections" + def __init__(self): OmpFunctionBreakpoint.__init__(self, "GOMP_sections_start") @@ -35,7 +36,8 @@ class GOMP_sections_start_Breakpoint(OmpFunctionBreakpoint): class GOMP_sections_end_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "sections" + def __init__(self, no_wait=False): OmpFunctionBreakpoint.__init__(self, "GOMP_sections_end{}".format("_nowait" if no_wait else "")) @@ -59,7 +61,8 @@ class GOMP_sections_end_Breakpoint(OmpFunctionBreakpoint): class GOMP_sections_next_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "sections" + def __init__(self): OmpFunctionBreakpoint.__init__(self, "GOMP_sections_next") diff --git a/model/task/environment/openmp/capture/gomp/GOMP_single_start.py b/model/task/environment/openmp/capture/gomp/GOMP_single_start.py index d4d64d8f89e2ee7e9af210affb755aa86742f339..d550080af9f43700eba4bd46e90696dec67a4c1b 100644 --- a/model/task/environment/openmp/capture/gomp/GOMP_single_start.py +++ b/model/task/environment/openmp/capture/gomp/GOMP_single_start.py @@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint class GOMP_single_start_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "single" def __init__(self): OmpFunctionBreakpoint.__init__(self, "GOMP_single_start") diff --git a/model/task/environment/openmp/capture/gomp/GOMP_task.py b/model/task/environment/openmp/capture/gomp/GOMP_task.py index acdf8bdb06345271190e8313cd9e963c2fb95846..6fd67b08f56df5e4949f25b65498801d58bcce3d 100644 --- a/model/task/environment/openmp/capture/gomp/GOMP_task.py +++ b/model/task/environment/openmp/capture/gomp/GOMP_task.py @@ -15,7 +15,8 @@ from .. import parse_omp_dependencies class GOMP_task_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "task" + task_ptr_to_task = {} current_per_thread = {} @@ -40,6 +41,7 @@ class GOMP_task_Breakpoint(OmpFunctionBreakpoint): class gomp_init_task_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "task deps" def set_dependencies(self, task, depend): NDEPEND_IDX, NOUT_IDX, DEP_OFFSET = range(3) @@ -145,6 +147,7 @@ class gomp_init_task_Breakpoint(OmpFunctionBreakpoint): class GOMP_task_function_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "task" def __init__(self, addr, fct_name): OmpFunctionBreakpoint.__init__(self, addr) diff --git a/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py b/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py index 58f9db16d15ba58e40ed20372f64f4542185e4f4..1305c818819e765247f92b95dc4030c063c71ac3 100644 --- a/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py +++ b/model/task/environment/openmp/capture/gomp/GOMP_taskwait.py @@ -14,6 +14,7 @@ from .. import current_worker class GOMP_taskwait_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "task deps" def __init__(self): OmpFunctionBreakpoint.__init__(self, "GOMP_taskwait") diff --git a/model/task/environment/openmp/capture/gomp/libgomp b/model/task/environment/openmp/capture/gomp/libgomp deleted file mode 120000 index 26e79e954d84f98354c21b3524c309bddd477897..0000000000000000000000000000000000000000 --- a/model/task/environment/openmp/capture/gomp/libgomp +++ /dev/null @@ -1 +0,0 @@ -/usr/src/debug/gcc-5.1.1-20150422/libgomp \ No newline at end of file diff --git a/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py b/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py index 6baee6939eb170024581b884a4d8d9d45deab3c8..283d3798bbd0128980030df86065532ea745c71b 100644 --- a/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py +++ b/model/task/environment/openmp/capture/gomp/omp_get_thread_num.py @@ -8,7 +8,9 @@ from ... import representation from .. import current_worker, OmpFunctionBreakpoint, get_omp_zone handlers = {} # opm operation -> handler -class omp_get_thread_num_Breakpoint(OmpFunctionBreakpoint): +class omp_get_thread_num_Breakpoint(OmpFunctionBreakpoint): + omp_set = "master" + def __init__(self): OmpFunctionBreakpoint.__init__(self, "omp_get_thread_num") @@ -19,6 +21,7 @@ class omp_get_thread_num_Breakpoint(OmpFunctionBreakpoint): return handler.prepare_before() if handler else None class omp_master_Handler(): + def prepare_before(self): if current_worker().number != 1: return None diff --git a/model/task/environment/openmp/capture/iomp/__init__.py b/model/task/environment/openmp/capture/iomp/__init__.py index 9948abb869fbb3804d46bfd6dfd1cc500c8b7e1a..a0dda602ac4b39e7a494a2dc4623105984c03754 100644 --- a/model/task/environment/openmp/capture/iomp/__init__.py +++ b/model/task/environment/openmp/capture/iomp/__init__.py @@ -13,18 +13,24 @@ def activate(): main_worker = representation.Worker(gdb.selected_thread()) gdb.selected_thread().name = str(main_worker) - log.critical("Activate OMPT task tracking") - gdb.execute("set ompt_status += ompt_status_track") + #log.critical("Activate OMPT task tracking") + #gdb.execute("set ompt_status += ompt_status_track") + # keep last to use objets above -from . import \ - kmpc_fork_call, \ - kmpc_launch_worker, \ - kmpc_barrier, \ - kmpc_single, \ - kmpc_critical, \ - kmpc_omp_task, \ - kmpc_for_static, \ - kmpc_omp_taskwait, \ - kmpc_master +from . import \ + kmpc_barrier, \ + kmpc_single, \ + kmpc_critical, \ + kmpc_omp_task, \ + kmpc_for_static, \ + kmpc_omp_taskwait, \ + kmpc_fork_call, \ + kmpc_launch_worker, \ + kmpc_master +log.warning("Many OpenMP feature disabled (hardcoded)") + +from . import kmpc_for_static + + from ..preload import omp_preload diff --git a/model/task/environment/openmp/capture/iomp/kmpc_barrier.py b/model/task/environment/openmp/capture/iomp/kmpc_barrier.py index e16c93ece1e2261caf6c7463c4308203d6a7d262..f0547756bf8d4428d20becb1bbbd76a1bdf73850 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_barrier.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_barrier.py @@ -21,6 +21,7 @@ def filename_lineno(): class kmpc_barrier_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "barrier" def __init__(self): OmpFunctionBreakpoint.__init__(self, "__kmpc_barrier") diff --git a/model/task/environment/openmp/capture/iomp/kmpc_critical.py b/model/task/environment/openmp/capture/iomp/kmpc_critical.py index e8065af2494b9b62a533633c51591b84758661a9..59985eba1ed55171272c9b74451e515cefda75b0 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_critical.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_critical.py @@ -11,7 +11,8 @@ from .. import OmpFunctionBreakpoint class kmpc_critical_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "critical" + def __init__(self): OmpFunctionBreakpoint.__init__(self, "__kmpc_critical") @@ -33,6 +34,7 @@ class kmpc_critical_Breakpoint(OmpFunctionBreakpoint): class kmpc_end_critical_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "critical" def __init__(self, named=False): OmpFunctionBreakpoint.__init__(self, "__kmpc_end_critical") diff --git a/model/task/environment/openmp/capture/iomp/kmpc_for_static.py b/model/task/environment/openmp/capture/iomp/kmpc_for_static.py index 19866c4117c3c9eb58e010e51556f22d35ce0df1..b799239d07b110e9d863467afd69850ebf00b8ea 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_for_static.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_for_static.py @@ -1,5 +1,7 @@ import gdb +import logging; log = logging.getLogger(__name__) + import mcgdb from mcgdb.toolbox.target import my_archi from mcgdb.toolbox import my_gdb @@ -14,20 +16,23 @@ def ptr_to_int(ptr): class kmpc_for_static_init_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "loop static" + def __init__(self, _type="4u"): OmpFunctionBreakpoint.__init__(self, "__kmpc_for_static_init_{}".format(_type)) def prepare_before (self): data = {} - data["loc"] = my_gdb.add_to_num(my_archi.nth_arg(5, my_archi.VOID_P)) - data["plower"] = my_archi.nth_arg(5, my_archi.INT) - data["pupper"] = my_archi.nth_arg(6, my_archi.INT) - + #my_gdb.addr2num(my_archi.nth_arg(5, my_archi.VOID_P)) # should access loc->psource + data["loc"] = my_gdb.addr2num(gdb.newest_frame().older().read_register("pc")) + data["plower"] = my_archi.nth_arg(5, my_archi.INT_P) + data["pupper"] = my_archi.nth_arg(6, my_archi.INT_P) + data["incr"] = my_archi.nth_arg(8, my_archi.INT) + data["loop"] = representation.ForLoopJob.get_loop_at_loc(data["loc"], ptr_to_int(data["plower"]), - ptr_to_int(data["pupper"])) - + ptr_to_int(data["pupper"]), + data["incr"]) return False, True, data def prepare_after(self, data): @@ -38,28 +43,45 @@ class kmpc_for_static_init_Breakpoint(OmpFunctionBreakpoint): class kmpc_for_static_fini_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "loop static" + def __init__(self,): OmpFunctionBreakpoint.__init__(self, "__kmpc_for_static_fini") def prepare_before (self): data = {} - worker = current_worker() - data["loop"] = loop = representation.ForLoopJob.get_current_loop_of(worker) + data["worker"] = worker = current_worker() + + data["loop"], data["iteration"] = loop, iteration \ + = representation.ForLoopJob.get_current_loop_of(worker) + + if not loop: + log.warn("spurious end") + return + loop.stop_work_of(worker) - + stop_after = loop.break_after_next loop.break_after_next = False - + + data["old-scheduler-locking"] = gdb.parameter("scheduler-locking") + if stop_after: + gdb.execute("set scheduler-locking on") + return False, stop_after, data def prepare_after(self, data): - iteration = loop.working - log_user.info("Stopped after loop {} iteration {}-{}.".format(loop, iteration[0], iteration[1])) + gdb.execute("set scheduler-locking {}".format(data["old-scheduler-locking"])) + log.warn("Stopped in worker {} after loop {} iteration {}-{}.".format( + data["worker"], + data["loop"], + data["iteration"][0], + data["iteration"][1])) return True def activate(): - kmpc_for_static_init_Breakpoint() + kmpc_for_static_init_Breakpoint(_type="4u") + kmpc_for_static_init_Breakpoint(_type="4") kmpc_for_static_fini_Breakpoint() diff --git a/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py b/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py index f8cfb2d09a7660955e2de0d4347a91af77776925..191b8f5b2632f29456cd1bac4fd8aa22b72b90d5 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_fork_call.py @@ -12,6 +12,8 @@ from .. import OmpFunctionBreakpoint class kmpc_fork_call_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "parallel" + inner_breakpoint = {} def __init__(self): diff --git a/model/task/environment/openmp/capture/iomp/kmpc_master.py b/model/task/environment/openmp/capture/iomp/kmpc_master.py index 92f79935f2631d49f71ae823bdb5f1e39added24..ec2509b20d70572562f92f20a7d147eb9dc585cb 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_master.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_master.py @@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint class kmpc_master_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "master" def __init__(self): OmpFunctionBreakpoint.__init__(self, "__kmpc_master") diff --git a/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py b/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py index eb41ce283d4978d51747831c08310452701f23b1..2d34f66866b83d4f7735fa96d2e15163bbe17ccd 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_omp_task.py @@ -16,6 +16,7 @@ HANDLE_TO_TASK = {} class kmp_check_deps_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "task deps" def __init__(self): OmpFunctionBreakpoint.__init__(self, "__kmp_check_deps") @@ -73,6 +74,7 @@ class kmp_check_deps_Breakpoint(OmpFunctionBreakpoint): class kmpc_omp_task_alloc_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "task" def __init__(self): OmpFunctionBreakpoint.__init__(self, "__kmpc_omp_task_alloc") @@ -111,7 +113,8 @@ class kmpc_omp_task_alloc_Breakpoint(OmpFunctionBreakpoint): class kmpc_task_function_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func - + omp_set = "task" + def __init__(self, fn): addr = str(fn).split("0x")[1] addr = "*0x"+str(addr).split(" ")[0] diff --git a/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py b/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py index 345bd62e824865dd38218bcf2acf3dcfcb941518..de776919e95a40456286b430d1ca7e139632d5ce 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_omp_taskwait.py @@ -14,6 +14,7 @@ from .. import current_worker class kmpc_taskwait_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "task deps" def __init__(self): OmpFunctionBreakpoint.__init__(self, "__kmpc_omp_taskwait") diff --git a/model/task/environment/openmp/capture/iomp/kmpc_single.py b/model/task/environment/openmp/capture/iomp/kmpc_single.py index e5a277e17bd60f323054a9c37b6b25ee0115a40f..8bd0d1d7bbf1711e99d44776487ab7844de89bf9 100644 --- a/model/task/environment/openmp/capture/iomp/kmpc_single.py +++ b/model/task/environment/openmp/capture/iomp/kmpc_single.py @@ -11,6 +11,7 @@ from .. import OmpFunctionBreakpoint class kmpc_single_Breakpoint(OmpFunctionBreakpoint): func_type = mcgdb.capture.FunctionTypes.conf_func + omp_set = "single" def __init__(self): OmpFunctionBreakpoint.__init__(self, "__kmpc_single") diff --git a/model/task/environment/openmp/interaction/__init__.py b/model/task/environment/openmp/interaction/__init__.py index 418e14dbf44ce3cf5740833dd5177c1503f38c09..0f5cc998b1ae1286bac282278867840aff1d49e8 100644 --- a/model/task/environment/openmp/interaction/__init__.py +++ b/model/task/environment/openmp/interaction/__init__.py @@ -4,14 +4,20 @@ import mcgdb representation = None -from . import step, show, \ - graph, sequence, info, start, all_out, \ - task, critical, barrier, sections, \ - attach, stacktree, loop +from . import enable -from . import ayudame_wrapper, ayudame_preload -from . import graph +# from . import step, show, \ +# graph, sequence, info, start, all_out, \ +# task, critical, barrier, sections, \ +# attach, stacktree +from . import info + +from . import loop + +# from . import ayudame_wrapper, ayudame_preload +# from . import graph + def activate(): global representation from .. import representation @@ -41,7 +47,7 @@ class cmd_omp_debug (gdb.Command): def invoke (self, args, from_tty): activate = "on" in args - print("omp debugging activated: {}".format(activate)) + print("OMP debugging activated: {}".format(activate)) from .. import toolbox toolbox.NO_PRINT = not activate diff --git a/model/task/environment/openmp/interaction/enable.py b/model/task/environment/openmp/interaction/enable.py new file mode 100644 index 0000000000000000000000000000000000000000..97a809901c24ec0105c85c864e0a18f53b6010ee --- /dev/null +++ b/model/task/environment/openmp/interaction/enable.py @@ -0,0 +1,68 @@ +import logging; log = logging.getLogger(__name__) +log_user = logging.getLogger("mcgdb.log.user") + +import gdb + +representation = None +capture = None + +def activate(): + global representation, capture + from .. import representation + from .. import capture + + cmd_omp_enable() + cmd_omp_disable() + +class cmd_omp_enable (gdb.Command): + enabled = [] + + def __init__ (self): + gdb.Command.__init__(self, "omp enable", gdb.COMMAND_OBSCURE) + + def invoke (self, args, from_tty): + disabled = [s for s in capture.OmpFunctionBreakpoint.breakpoint_sets.keys() if s not in cmd_omp_enable.enabled] + + found = True + if args and not args in disabled: + log_user.info("Cannot find '{}' breakpoint sets.".format(args)) + found = False + if not found or not args: + log_user.info("Sets that can be enabled: {}".format(", ".join(disabled))) + return + + for bpt in capture.OmpFunctionBreakpoint.breakpoint_sets[args]: + bpt.enabled = True + log_user.info("Enabling {}@{}...".format(bpt.__class__.__name__, bpt.location)) + + assert args not in cmd_omp_enable.enabled + cmd_omp_enable.enabled.append(args) + + def complete (self, text, word): + disabled = [s for s in capture.OmpFunctionBreakpoint.breakpoint_sets.keys() if s not in cmd_omp_enable.enabled] + + return [setname for setname in disabled if setname.startswith(word)] + +class cmd_omp_disable (gdb.Command): + + def __init__ (self): + gdb.Command.__init__(self, "omp disable", gdb.COMMAND_OBSCURE) + + def invoke (self, args, from_tty): + found = True + if args and not args in cmd_omp_enable.enabled: + log_user.info("Cannot find '{}' breakpoint sets.".format(args)) + found = False + if not found or not args: + log_user.info("Sets that can be disabled: {}".format(", ".join(cmd_omp_enable.enabled))) + return + + for bpt in capture.OmpFunctionBreakpoint.breakpoint_sets[args]: + bpt.enabled = False + log_user.info("Disabling {}@{}...".format(bpt.__class__.__name__, bpt.location)) + + assert args in cmd_omp_enable.enabled + cmd_omp_enable.enabled.remove(args) + + def complete (self, text, word): + return [setname for setname in cmd_omp_enable.enabled if setname.startswith(word)] diff --git a/model/task/environment/openmp/interaction/graph.py b/model/task/environment/openmp/interaction/graph.py index b5cf4900f8379cf7413a4a77b5e0091dd17584d2..134c6563cdb5a14c25d2e5fe44d017df95c81db4 100644 --- a/model/task/environment/openmp/interaction/graph.py +++ b/model/task/environment/openmp/interaction/graph.py @@ -47,6 +47,7 @@ def activate(): try: import networkx as nx # https://pypi.python.org/pypi/networkx/ + import matplotlib as mpl ; mpl.use('Agg') # Force matplotlib/nx to not use any Xwindows backend. #import pygraphviz as pgv # https://pygraphviz.github.io/ except ImportError as e: log.warning("Could not initialize {} package: '{}'".format(__name__, e)) diff --git a/model/task/environment/openmp/interaction/loop.py b/model/task/environment/openmp/interaction/loop.py index ca4ccb968a6eb7be42e16c2f95467fe7d22514f9..eb8f1f9bf18e788d4caad86f4496273690a7bc51 100644 --- a/model/task/environment/openmp/interaction/loop.py +++ b/model/task/environment/openmp/interaction/loop.py @@ -1,6 +1,11 @@ import gdb +import logging; log = logging.getLogger(__name__) +log_user = logging.getLogger("mcgdb.log.user") + from mcgdb.toolbox import my_gdb +from mcgdb.toolbox import aspect +import mcgdb.interaction representation = None current_worker = None @@ -12,12 +17,13 @@ def activate(): cmd_omp_loop() cmd_omp_loop_profile() + cmd_omp_loop_profile_iterations() cmd_omp_loop_last_range() cmd_omp_loop_break() cmd_omp_loop_break_after_next() aspect.register("loop-profile", loop_aspects) - + class cmd_omp_loop (gdb.Command): def __init__ (self): gdb.Command.__init__(self, "omp loop", gdb.COMMAND_OBSCURE, prefix=True) @@ -44,7 +50,7 @@ class cmd_omp_loop_break (gdb.Command): class cmd_omp_loop_break_after_next (gdb.Command): def __init__ (self): gdb.Command.__init__(self, "omp loop break after_next", gdb.COMMAND_OBSCURE, prefix=1) - + def invoke (self, args, from_tty): last_loop = representation.ForLoopJob.get_last_loop() @@ -52,58 +58,58 @@ class cmd_omp_loop_break_after_next (gdb.Command): log_user.warn("Could not find any last loop") return - action = "Enable" if not self.break_after_next else "Disable" - - log_user.info("{} break-after-next breakpoint on loop {}.".format(action, last_loop)) - self.break_after_next = not self.break_after_next + action = "Enable" if not last_loop.break_after_next else "Disable" + + log_user.info("{} break-after-next breakpoint on loop {}.".format(action, repr(last_loop))) + last_loop.break_after_next = not last_loop.break_after_next + +iteration_profiling_enabled = False -profiling_enabled = False class cmd_omp_loop_profile (gdb.Command): def __init__ (self): - gdb.Command.__init__(self, "omp loop profile", gdb.COMMAND_OBSCURE, prefix=1) + gdb.Command.__init__(self, "omp loop profile", gdb.COMMAND_OBSCURE, prefix=True) - def invoke (self, args, from_tty): - global profiling_enabled + def invoke (self, arg, from_tty): + log_user.warn("Please specify what kind of profiling you want to do.") - profiling_enabled = not profiling_enabled - action = "enabled" if profiling_enabled else "disabled" - - log_user.info("Loop profiling {}.".format(action)) - - if not profiling_enabled and gdb.parameter("scheduler-locking") == "on": - gdb.execute("set scheduler-locking off") - log_user.info("Scheduler locking disabled.") - -class cmd_omp_loop_break_profile (gdb.Command): +class cmd_omp_loop_profile_iterations (gdb.Command): def __init__ (self): - gdb.Command.__init__(self, "omp loop profile break", gdb.COMMAND_OBSCURE, prefix=1) + gdb.Command.__init__(self, "omp loop profile iterations", gdb.COMMAND_OBSCURE, prefix=1) def invoke (self, args, from_tty): - cpt, cmpt, val = args.split(" ") + global iteration_profiling_enabled - log_user.info("Breakpoint set on profile {}.".format(args)) + iteration_profiling_enabled = not iteration_profiling_enabled + action = "enabled" if iteration_profiling_enabled else "disabled" + + log_user.info("Loop iteration profiling {}.".format(action)) + + if not iteration_profiling_enabled and gdb.parameter("scheduler-locking") == "on": + gdb.execute("set scheduler-locking off") + log_user.info("Scheduler locking disabled.") def loop_aspects(Tracks): from .. import representation - @Tracks(representation.TaskJob) + @Tracks(representation.ForLoopJob) class ForLoopJob: def __init__(this): - print("start loop {}".format(this.self)) - if profiling_enabled: - print("set scheduler locking") + pass def start_work_on(this): - print("loop {} {}".format(this.args.lower, this.args.upper)) - if profiling_enabled: - print("start profiling") + if iteration_profiling_enabled: + gdb.execute("set scheduler-locking on") + #print("START profiling {} {}".format(this.args.lower, this.args.upper)) + gdb.execute("profile manual start") def stop_work_of(this): - print("loop iteration done") - if profiling_enabled: - print("stop profiling") + if iteration_profiling_enabled: + gdb.execute("profile manual stop") + gdb.execute("set scheduler-locking off") def done(this): - print("loop done") - if profiling_enabled: - print("set scheduler locking") + global iteration_profiling_enabled + + if iteration_profiling_enabled: + mcgdb.interaction.push_stop_request("Iteration profiling finished.") + iteration_profiling_enabled = False diff --git a/model/task/environment/openmp/interaction/profile.py b/model/task/environment/openmp/interaction/profile.py index 13e5b450889f1e26a38dc9269df789fe7e1d11d4..c6674e2cf1dd72a74f37dbda114692285d9dc300 100644 --- a/model/task/environment/openmp/interaction/profile.py +++ b/model/task/environment/openmp/interaction/profile.py @@ -1,3 +1,6 @@ +import logging; log = logging.getLogger(__name__) +log_user = logging.getLogger("mcgdb.log.user.openmp.profile") + import gdb from mcgdb.toolbox import my_gdb @@ -15,4 +18,5 @@ class cmd_omp_profile (gdb.Command): def __init__ (self): gdb.Command.__init__(self, "omp profile", gdb.COMMAND_OBSCURE, prefix=True) - + def invoke (self, arg, from_tty): + log_user.warn("Please specify what kind of profiling you want to do.") diff --git a/model/task/environment/openmp/representation.py b/model/task/environment/openmp/representation.py index d362b7a7d67abcd5ba92b72462b4445229a6fafc..27fd45f31baf97a49a1020ec3d4521f498d43826 100644 --- a/model/task/environment/openmp/representation.py +++ b/model/task/environment/openmp/representation.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import logging; log = logging.getLogger(__name__) from collections import OrderedDict @@ -1035,12 +1033,12 @@ class TaskJob(Job): @my_gdb.Dicted class ForLoopJob(Job, aspect.Tracker): @staticmethod - def get_loop_at_loc(loc, lower, upper): + def get_loop_at_loc(loc, lower, upper, incr): try: return ForLoopJob.dict_[loc] except KeyError: pass - return ForLoopJob(loc, lower, upper) + return ForLoopJob(loc, lower, upper, incr) @staticmethod def get_last_loop(): @@ -1057,31 +1055,54 @@ class ForLoopJob(Job, aspect.Tracker): except KeyError: pass return None, None + + @staticmethod + def get_current_loop_of(worker): + loop, iteration = ForLoopJob.get_last_loop_of(worker) + + # if we have a last loop, and it's not finished + if loop and iteration[-1]: + return loop, iteration + else: + return None, None - def __init__(self, loc, lower, upper): + def __init__(self, loc, lower, upper, incr): Job.__init__(self) ForLoopJob.init_dict(loc, self) - + self.loc = loc self.lower = lower - self.upper == upper - + self.upper = upper + self.incr = incr + self.working = {} self.break_after_next = False + + self.work_remaining = int((upper - lower + 1)/incr) # +1 because of boundaries + self.workers_done = 0 def start_work_on(self, worker, lower, upper): assert worker not in self.working - + self.working[worker] = [lower, upper, True] def stop_work_of(self, worker): assert worker in self.working assert self.working[worker][-1] is True - self.working[worker] = False + self.working[worker][-1] = False + lower, upper = self.working[worker][:2] + self.work_remaining -= (upper - lower + 1) # +1 because of boundaries + + self.workers_done += 1 + + if self.work_remaining == 0 and len(Worker.list_) == self.workers_done: + self.done() + def done(self): + print("LOOP {} done".format(self)) pass class Init: diff --git a/toolbox/my_gdb.py b/toolbox/my_gdb.py index ac52bbbc6cec1c0a851dfff1e8ebf25dc4053865..81c903802874e7a387ae1ad43350955f61016524 100644 --- a/toolbox/my_gdb.py +++ b/toolbox/my_gdb.py @@ -907,6 +907,6 @@ def find_type(orig, name): def initialize(): #gdb.events.new_objfile.connect(AllInfBreakpoint.handler_new_objfile) - log.warn("Signal handler NOT registered (commented out)") + log.warn("Signal handler NOT registered (hardcoded)") #signal.signal(signal.SIGINT, signal_handler) diff --git a/toolbox/paje.py b/toolbox/paje.py index 91a3a29ef621e91916e7b5b7e8f38c22b0007fd4..54401bd87c75f09f04493a52168481098b3000d9 100644 --- a/toolbox/paje.py +++ b/toolbox/paje.py @@ -211,6 +211,7 @@ class cmd_printPaje(gdb.Command): def invoke_limited(self, to_screen, to_file, tids): Event.feed_raw(to_file, tids) +PAJE_ENABLED = False @my_gdb.internal def initialize(): global tempfile, ctypes, ctypes, fcntl, initialized @@ -218,6 +219,10 @@ def initialize(): import ctypes import fcntl + if not PAJE_ENABLED: + log.warn("Paje tracing disabled (hardcoded).") + return + global poti_lib try: libc = ctypes.CDLL("libc.so.6") @@ -229,8 +234,8 @@ def initialize(): log_user.debug("Paje trace output enabled") initialized = True except Exception as e: - log.warn("Paje: Could *not* initialize Paje/libpoti tracing") - log.warn("Paje: Falling back on raw tracing.") - log.info(e) + log.warn("Could *not* initialize Paje/libpoti tracing") + log.warn("Falling back on raw tracing.") + log.warn(e) cmd_printPaje(limited=True) initialized = None diff --git a/toolbox/python_utils.py b/toolbox/python_utils.py index b4ca364d267f7a7171e13355d4327302d832fb52..bc44e038dc9cd2f500e3ce92180470aa92018a12 100644 --- a/toolbox/python_utils.py +++ b/toolbox/python_utils.py @@ -23,7 +23,8 @@ except ImportError: try: from profilehooks import profile as profile_decorator # https://github.com/mgedmin/profilehooks except ImportError as e: - log_import.error("Cannot import profilehooks package, mcgdb profiling will not be available. ({})".format(e)) + log.warning("Cannot import 'profilehooks' package, mcgdb profiling won't be available:") + log.warning(e) profile_decorator = None DO_PROFILE = False