All logging should use call new functions

Signed-off-by: colramos-amd <colramos@amd.com>


[ROCm/rocprofiler-compute commit: 5bf38a4fed]
This commit is contained in:
colramos-amd
2024-01-30 17:25:16 -06:00
committed by Karl W. Schulz
parent cfdf288cba
commit a1371462ba
26 changed files with 474 additions and 337 deletions
+2 -1
View File
@@ -29,6 +29,7 @@ import locale
import logging import logging
from utils.utils import error from utils.utils import error
from omniperf_base import Omniperf from omniperf_base import Omniperf
from utils.utils import console_error
def main(): def main():
try: try:
@@ -48,7 +49,7 @@ def main():
elif mode == "analyze": elif mode == "analyze":
omniperf.run_analysis() omniperf.run_analysis()
else: else:
omniperf.error("Unsupported execution mode") console_error("Unsupported execution mode")
sys.exit(0) sys.exit(0)
@@ -24,12 +24,11 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import os import os
import logging
import sys import sys
import copy import copy
from collections import OrderedDict from collections import OrderedDict
from pathlib import Path from pathlib import Path
from utils.utils import demarcate, error, is_workload_empty from utils.utils import demarcate, is_workload_empty, console_log, console_debug, console_error
from utils import schema, file_io, parser from utils import schema, file_io, parser
import pandas as pd import pandas as pd
from tabulate import tabulate from tabulate import tabulate
@@ -103,7 +102,7 @@ class OmniAnalyze_Base:
print(prefix + key, "->", value) print(prefix + key, "->", value)
sys.exit(0) sys.exit(0)
else: else:
error("Unsupported arch") console_error("Unsupported arch")
@demarcate @demarcate
def load_options(self, normalization_filter): def load_options(self, normalization_filter):
@@ -117,16 +116,24 @@ class OmniAnalyze_Base:
parser.build_metric_value_string(v.dfs, v.dfs_type, normalization_filter) parser.build_metric_value_string(v.dfs, v.dfs_type, normalization_filter)
args = self.__args args = self.__args
# Error checking for multiple runs and multiple gpu_kernel filters # Error checking for multiple runs and multiple kernel filters
if args.gpu_kernel and (len(args.path) != len(args.gpu_kernel)): if args.gpu_kernel and (len(args.path) != len(args.gpu_kernel)):
if len(args.gpu_kernel) == 1: if len(args.gpu_kernel) == 1:
for i in range(len(args.path) - 1): for i in range(len(args.path) - 1):
args.gpu_kernel.extend(args.gpu_kernel) args.gpu_kernel.extend(args.gpu_kernel)
else: else:
<<<<<<< HEAD
error( error(
"Error: the number of --filter-kernels doesn't match the number of --dir." "Error: the number of --filter-kernels doesn't match the number of --dir."
) )
=======
console_error(
"analysis"
"The number of -k/--kernel doesn't match the number of --dir."
)
>>>>>>> All logging should use call new functions
@demarcate @demarcate
def initalize_runs(self, normalization_filter=None): def initalize_runs(self, normalization_filter=None):
if self.__args.list_metrics: if self.__args.list_metrics:
@@ -165,16 +172,16 @@ class OmniAnalyze_Base:
def sanitize(self): def sanitize(self):
"""Perform sanitization of inputs""" """Perform sanitization of inputs"""
if not self.__args.path: if not self.__args.path:
error("The following arguments are required: -p/--path") console_error("The following arguments are required: -p/--path")
# verify not accessing parent directories # verify not accessing parent directories
if ".." in str(self.__args.path): if ".." in str(self.__args.path):
error("Access denied. Cannot access parent directories in path (i.e. ../)") console_error("Access denied. Cannot access parent directories in path (i.e. ../)")
# ensure absolute path # ensure absolute path
for dir in self.__args.path: for dir in self.__args.path:
full_path = os.path.abspath(dir[0]) full_path = os.path.abspath(dir[0])
dir[0] = full_path dir[0] = full_path
if not os.path.isdir(dir[0]): if not os.path.isdir(dir[0]):
error("Invalid directory {}\nPlease try again.".format(dir[0])) console_error("Invalid directory {}\nPlease try again.".format(dir[0]))
# validate profiling data # validate profiling data
is_workload_empty(dir[0]) is_workload_empty(dir[0])
@@ -183,9 +190,22 @@ class OmniAnalyze_Base:
# ---------------------------------------------------- # ----------------------------------------------------
@abstractmethod @abstractmethod
def pre_processing(self): def pre_processing(self):
<<<<<<< HEAD
"""Perform initialization prior to analysis.""" """Perform initialization prior to analysis."""
logging.debug("[analysis] prepping to do some analysis") logging.debug("[analysis] prepping to do some analysis")
logging.info("[analysis] deriving Omniperf metrics...") logging.info("[analysis] deriving Omniperf metrics...")
=======
"""Perform initialization prior to analysis.
"""
console_debug(
"analysis",
"prepping to do some analysis"
)
console_log(
"analysis",
"deriving Omniperf metrics..."
)
>>>>>>> All logging should use call new functions
# initalize output file # initalize output file
self._output = ( self._output = (
open(self.__args.output_file, "w+") if self.__args.output_file else sys.stdout open(self.__args.output_file, "w+") if self.__args.output_file else sys.stdout
@@ -213,5 +233,14 @@ class OmniAnalyze_Base:
@abstractmethod @abstractmethod
def run_analysis(self): def run_analysis(self):
<<<<<<< HEAD
"""Run analysis.""" """Run analysis."""
logging.debug("[analysis] generating analysis") logging.debug("[analysis] generating analysis")
=======
"""Run analysis.
"""
console_debug(
"analysis",
"generating analysis"
)
>>>>>>> All logging should use call new functions
@@ -23,7 +23,7 @@
##############################################################################el ##############################################################################el
from omniperf_analyze.analysis_base import OmniAnalyze_Base from omniperf_analyze.analysis_base import OmniAnalyze_Base
from utils.utils import demarcate, error from utils.utils import demarcate, console_error
from utils import file_io, parser, tty from utils import file_io, parser, tty
from utils.kernel_name_shortener import kernel_name_shortener from utils.kernel_name_shortener import kernel_name_shortener
@@ -37,7 +37,7 @@ class cli_analysis(OmniAnalyze_Base):
"""Perform any pre-processing steps prior to analysis.""" """Perform any pre-processing steps prior to analysis."""
super().pre_processing() super().pre_processing()
if self.get_args().random_port: if self.get_args().random_port:
error("--gui flag is required to enable --random-port") console_error("--gui flag is required to enable --random-port")
for d in self.get_args().path: for d in self.get_args().path:
# demangle and overwrite original 'Kernel_Name' # demangle and overwrite original 'Kernel_Name'
kernel_name_shortener(d[0], self.get_args().kernel_verbose) kernel_name_shortener(d[0], self.get_args().kernel_verbose)
@@ -23,12 +23,11 @@
##############################################################################el ##############################################################################el
from omniperf_analyze.analysis_base import OmniAnalyze_Base from omniperf_analyze.analysis_base import OmniAnalyze_Base
from utils.utils import demarcate, error from utils.utils import demarcate, console_debug, console_error
from utils import file_io, parser from utils import file_io, parser
from utils.gui import build_bar_chart, build_table_chart from utils.gui import build_bar_chart, build_table_chart
import os import os
import logging
import random import random
import copy import copy
import dash import dash
@@ -100,18 +99,31 @@ class webui_analysis(OmniAnalyze_Base):
def generate_from_filter( def generate_from_filter(
disp_filt, kernel_filter, gcd_filter, norm_filt, top_n_filt, div_children disp_filt, kernel_filter, gcd_filter, norm_filt, top_n_filt, div_children
): ):
logging.debug("[analysis] gui normalization is %s" % norm_filt) console_debug(
"analysis",
"gui normalization is %s" % norm_filt
)
base_data = self.initalize_runs() # Re-initalizes everything base_data = self.initalize_runs() # Re-initalizes everything
panel_configs = copy.deepcopy(arch_configs.panel_configs) panel_configs = copy.deepcopy(arch_configs.panel_configs)
# Generate original raw df # Generate original raw df
base_data[base_run].raw_pmc = file_io.create_df_pmc( base_data[base_run].raw_pmc = file_io.create_df_pmc(self.dest_dir, self.get_args().verbose)
self.dest_dir, self.get_args().verbose console_debug(
"analysis",
"gui dispatch filter is %s" % disp_filt
)
console_debug(
"analysis",
"gui kernel filter is %s" % kernel_filter
)
console_debug(
"analysis",
"gui gpu filter is %s" % gcd_filter
)
console_debug(
"analysis",
"gui top-n filter is %s" % top_n_filt
) )
logging.debug("[analysis] gui dispatch filter is %s" % disp_filt)
logging.debug("[analysis] gui kernel filter is %s" % kernel_filter)
logging.debug("[analysis] gui gpu filter is %s" % gcd_filter)
logging.debug("[analysis] gui top-n filter is %s" % top_n_filt)
base_data[base_run].filter_kernel_ids = kernel_filter base_data[base_run].filter_kernel_ids = kernel_filter
base_data[base_run].filter_gpu_ids = gcd_filter base_data[base_run].filter_gpu_ids = gcd_filter
base_data[base_run].filter_dispatch_ids = disp_filt base_data[base_run].filter_dispatch_ids = disp_filt
@@ -287,9 +299,7 @@ class webui_analysis(OmniAnalyze_Base):
self.arch = self._runs[self.dest_dir].sys_info.iloc[0]["gpu_arch"] self.arch = self._runs[self.dest_dir].sys_info.iloc[0]["gpu_arch"]
else: else:
self.error( console_error("Multiple runs not yet supported in GUI. Retry without --gui flag.")
"Multiple runs not yet supported in GUI. Retry without --gui flag."
)
@demarcate @demarcate
def run_analysis(self): def run_analysis(self):
@@ -23,11 +23,11 @@
##############################################################################el ##############################################################################el
import argparse import argparse
import logging
import sys import sys
import os import os
from pathlib import Path from pathlib import Path
import shutil import shutil
<<<<<<< HEAD
from utils.specs import generate_machine_specs from utils.specs import generate_machine_specs
from utils.utils import ( from utils.utils import (
demarcate, demarcate,
@@ -38,6 +38,11 @@ from utils.utils import (
error, error,
get_submodules, get_submodules,
) )
=======
from utils.specs import get_machine_specs
from utils.utils import demarcate, get_version, get_version_display, detect_rocprof, get_submodules, console_log, console_error
from utils.logger import setup_logging
>>>>>>> All logging should use call new functions
from argparser import omniarg_parser from argparser import omniarg_parser
import config import config
import pandas as pd import pandas as pd
@@ -70,7 +75,7 @@ class Omniperf:
self.__supported_archs = SUPPORTED_ARCHS self.__supported_archs = SUPPORTED_ARCHS
self.__mspec: MachineSpecs = None # to be initalized in load_soc_specs() self.__mspec: MachineSpecs = None # to be initalized in load_soc_specs()
self.setup_logging() setup_logging()
self.set_version() self.set_version()
self.parse_args() self.parse_args()
@@ -80,9 +85,15 @@ class Omniperf:
self.detect_profiler() self.detect_profiler()
elif self.__mode == "analyze": elif self.__mode == "analyze":
self.detect_analyze() self.detect_analyze()
<<<<<<< HEAD
logging.info("Execution mode = %s" % self.__mode) logging.info("Execution mode = %s" % self.__mode)
=======
console_log("Execution mode = %s" % self.__mode)
>>>>>>> All logging should use call new functions
def print_graphic(self): def print_graphic(self):
"""Log program name as ascii art to terminal.""" """Log program name as ascii art to terminal."""
ascii_art = r""" ascii_art = r"""
@@ -92,6 +103,7 @@ class Omniperf:
| |_| | | | | | | | | | | |_) | __/ | | _| | |_| | | | | | | | | | | |_) | __/ | | _|
\___/|_| |_| |_|_| |_|_| .__/ \___|_| |_| \___/|_| |_| |_|_| |_|_| .__/ \___|_| |_|
|_| |_|
<<<<<<< HEAD
""" """
logging.info(ascii_art) logging.info(ascii_art)
@@ -119,6 +131,10 @@ class Omniperf:
sys.exit(1) sys.exit(1)
logging.basicConfig(format="%(message)s", level=loglevel, stream=sys.stdout) logging.basicConfig(format="%(message)s", level=loglevel, stream=sys.stdout)
=======
'''
print(ascii_art)
>>>>>>> All logging should use call new functions
def get_mode(self): def get_mode(self):
return self.__mode return self.__mode
@@ -138,8 +154,7 @@ class Omniperf:
or self.__args.use_rocscope or self.__args.use_rocscope
): ):
if not shutil.which("rocscope"): if not shutil.which("rocscope"):
logging.error("Rocscope must be in PATH") console_error("Rocscope must be in PATH")
sys.exit(1)
else: else:
self.__profiler_mode = "rocscope" self.__profiler_mode = "rocscope"
else: else:
@@ -149,10 +164,15 @@ class Omniperf:
elif str(rocprof_cmd).endswith("rocprofv2"): elif str(rocprof_cmd).endswith("rocprofv2"):
self.__profiler_mode = "rocprofv2" self.__profiler_mode = "rocprofv2"
else: else:
<<<<<<< HEAD
error( error(
"Incompatible profiler: %s. Supported profilers include: %s" "Incompatible profiler: %s. Supported profilers include: %s"
% (rocprof_cmd, get_submodules("omniperf_profile")) % (rocprof_cmd, get_submodules("omniperf_profile"))
) )
=======
console_error("Incompatible profiler: %s. Supported profilers include: %s" % (rocprof_cmd, get_submodules('omniperf_profile')))
>>>>>>> All logging should use call new functions
return return
@@ -175,12 +195,27 @@ class Omniperf:
# NB: This checker is a bit redundent. We already check this in specs module # NB: This checker is a bit redundent. We already check this in specs module
if arch not in self.__supported_archs.keys(): if arch not in self.__supported_archs.keys():
<<<<<<< HEAD
error("%s is an unsupported SoC" % arch) error("%s is an unsupported SoC" % arch)
soc_module = importlib.import_module("omniperf_soc.soc_" + arch) soc_module = importlib.import_module("omniperf_soc.soc_" + arch)
soc_class = getattr(soc_module, arch + "_soc") soc_class = getattr(soc_module, arch + "_soc")
self.__soc[arch] = soc_class(self.__args, self.__mspec) self.__soc[arch] = soc_class(self.__args, self.__mspec)
return return
=======
console_error("%s is an unsupported SoC" % arch)
else:
self.__soc_name.add(target)
if hasattr(self.__args, 'target'):
self.__args.target = target
soc_module = importlib.import_module('omniperf_soc.soc_'+arch)
soc_class = getattr(soc_module, arch+'_soc')
self.__soc[arch] = soc_class(self.__args)
console_log("SoC = %s" % self.__soc_name)
return arch
>>>>>>> All logging should use call new functions
@demarcate @demarcate
def parse_args(self): def parse_args(self):
@@ -202,8 +237,7 @@ class Omniperf:
print(generate_machine_specs(self.__args)) print(generate_machine_specs(self.__args))
sys.exit(0) sys.exit(0)
parser.print_help(sys.stderr) parser.print_help(sys.stderr)
error("Omniperf requires a valid mode.") console_error("Omniperf requires you pass a valid mode. Detected None.")
return return
@demarcate @demarcate
@@ -217,7 +251,9 @@ class Omniperf:
self.__args.path, self.__args.name, self.__mspec.gpu_model self.__args.path, self.__args.name, self.__mspec.gpu_model
) )
logging.info("Profiler choice = %s" % self.__profiler_mode) console_log(
"Profiler choice = %s" % self.__profiler_mode
)
# instantiate desired profiler # instantiate desired profiler
if self.__profiler_mode == "rocprofv1": if self.__profiler_mode == "rocprofv1":
@@ -239,8 +275,7 @@ class Omniperf:
self.__args, self.__profiler_mode, self.__soc[self.__mspec.gpu_arch] self.__args, self.__profiler_mode, self.__soc[self.__mspec.gpu_arch]
) )
else: else:
logging.error("Unsupported profiler") console_error("Unsupported profiler")
sys.exit(1)
# ----------------------- # -----------------------
# run profiling workflow # run profiling workflow
@@ -275,7 +310,9 @@ class Omniperf:
def run_analysis(self): def run_analysis(self):
self.print_graphic() self.print_graphic()
logging.info("Analysis mode = %s" % self.__analyze_mode) console_log(
"Analysis mode = %s" % self.__analyze_mode
)
if self.__analyze_mode == "cli": if self.__analyze_mode == "cli":
from omniperf_analyze.analysis_cli import cli_analysis from omniperf_analyze.analysis_cli import cli_analysis
@@ -286,7 +323,7 @@ class Omniperf:
analyzer = webui_analysis(self.__args, self.__supported_archs) analyzer = webui_analysis(self.__args, self.__supported_archs)
else: else:
error("Unsupported anlaysis mode -> %s" % self.__analyze_mode) console_error("Unsupported anlaysis mode -> %s" % self.__analyze_mode)
# ----------------------- # -----------------------
# run analysis workflow # run analysis workflow
@@ -23,19 +23,11 @@
##############################################################################el ##############################################################################el
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import logging
import glob import glob
import sys import sys
import os import os
import re import re
from utils.utils import ( from utils.utils import capture_subprocess_output, run_prof, gen_sysinfo, run_rocscope, demarcate, console_log, console_debug, console_error, console_warning, print_status
capture_subprocess_output,
run_prof,
gen_sysinfo,
run_rocscope,
error,
demarcate,
)
import config import config
import pandas as pd import pandas as pd
@@ -105,8 +97,7 @@ class OmniProfiler_Base:
elif type(self.__args.path) == list: elif type(self.__args.path) == list:
files = self.__args.path files = self.__args.path
else: else:
logging.error("ERROR: Invalid workload_dir") console_error("Invalid workload directory. Cannot resolve %s" % self.__args.path)
sys.exit(1)
df = None df = None
for i, file in enumerate(files): for i, file in enumerate(files):
@@ -124,8 +115,7 @@ class OmniProfiler_Base:
+ key.astype(str) + key.astype(str)
) )
else: else:
print("ERROR: Unrecognized --join-type") console_error("%s is an unrecognized option for --join-type" % self.__args.join_type)
sys.exit(1)
if df is None: if df is None:
df = _df df = _df
@@ -162,15 +152,20 @@ class OmniProfiler_Base:
for key, cols in duplicate_cols.items(): for key, cols in duplicate_cols.items():
_df = df[cols] _df = df[cols]
if not test_df_column_equality(_df): if not test_df_column_equality(_df):
msg = "WARNING: Detected differing {} values while joining pmc_perf.csv".format( msg = (
key "Detected differing {} values while joining pmc_perf.csv".format(
key
)
) )
logging.warning(msg + "\n") console_warning(msg + "\n")
else: else:
msg = "Successfully joined {} in pmc_perf.csv".format(key) msg = "Successfully joined {} in pmc_perf.csv".format(key)
logging.debug(msg + "\n") console_debug(msg + "\n")
if test_df_column_equality(_df) and self.__args.verbose: if test_df_column_equality(_df) and self.__args.verbose:
logging.info(msg) console_log(
"profile",
msg
)
# now, we can: # now, we can:
#   A) throw away any of the "boring" duplicates #   A) throw away any of the "boring" duplicates
@@ -265,69 +260,65 @@ class OmniProfiler_Base:
# ---------------------------------------------------- # ----------------------------------------------------
@abstractmethod @abstractmethod
def pre_processing(self): def pre_processing(self):
"""Perform any pre-processing steps prior to profiling.""" """Perform any pre-processing steps prior to profiling.
logging.debug("[profiling] pre-processing using %s profiler" % self.__profiler) """
console_debug(
"profiling",
"pre-processing using %s profiler" % self.__profiler
)
# verify soc compatibility # verify soc compatibility
if self.__profiler not in self._soc.get_compatible_profilers(): if self.__profiler not in self._soc.get_compatible_profilers():
error( console_error("%s is not enabled in %s. Available profilers include: %s" % (self._soc.get_arch(), self.__profiler, self._soc.get_compatible_profilers()))
"%s is not enabled in %s. Available profilers include: %s"
% (
self._soc.get_arch(),
self.__profiler,
self._soc.get_compatible_profilers(),
)
)
# verify not accessing parent directories # verify not accessing parent directories
if ".." in str(self.__args.path): if ".." in str(self.__args.path):
error("Access denied. Cannot access parent directories in path (i.e. ../)") console_error("Access denied. Cannot access parent directories in path (i.e. ../)")
# verify correct formatting for application binary # verify correct formatting for application binary
self.__args.remaining = self.__args.remaining[1:] self.__args.remaining = self.__args.remaining[1:]
if self.__args.remaining: if self.__args.remaining:
if not os.path.isfile(self.__args.remaining[0]): if not os.path.isfile(self.__args.remaining[0]):
error( console_error("Your command %s doesn't point to a executable. Please verify." % self.__args.remaining[0])
"Your command %s doesn't point to a executable. Please verify."
% self.__args.remaining[0]
)
self.__args.remaining = " ".join(self.__args.remaining) self.__args.remaining = " ".join(self.__args.remaining)
else: else:
error( console_error("Profiling command required. Pass application executable after -- at the end of options.\n\t\ti.e. omniperf profile -n vcopy -- ./vcopy 1048576 256")
"Profiling command required. Pass application executable after -- at the end of options.\n\t\ti.e. omniperf profile -n vcopy -- ./vcopy 1048576 256"
)
# verify name meets MongoDB length requirements and no illegal chars # verify name meets MongoDB length requirements and no illegal chars
if len(self.__args.name) > 35: if len(self.__args.name) > 35:
error("-n/--name exceeds 35 character limit. Try again.") console_error("-n/--name exceeds 35 character limit. Try again.")
if self.__args.name.find(".") != -1 or self.__args.name.find("-") != -1: if self.__args.name.find(".") != -1 or self.__args.name.find("-") != -1:
error("'-' and '.' are not permitted in -n/--name") console_error("'-' and '.' are not permitted in -n/--name")
@abstractmethod @abstractmethod
def run_profiling(self, version: str, prog: str): def run_profiling(self, version:str, prog:str):
"""Run profiling.""" """Run profiling.
logging.debug( """
"[profiling] performing profiling using %s profiler" % self.__profiler console_debug(
"profiling",
"performing profiling using %s profiler" % self.__profiler
) )
# log basic info # log basic info
logging.info(str(prog) + " ver: " + str(version)) console_log(str(prog) + " ver: " + str(version))
logging.info("Path: " + str(os.path.abspath(self.__args.path))) console_log("Path: " + str(os.path.abspath(self.__args.path)))
logging.info("Target: " + str(self._soc._mspec.gpu_model)) console_log("Target: " + str(self.__args.gpu_model))
logging.info("Command: " + str(self.__args.remaining)) console_log("Command: " + str(self.__args.remaining))
logging.info("Kernel Selection: " + str(self.__args.kernel)) console_log("Kernel Selection: " + str(self.__args.kernel))
logging.info("Dispatch Selection: " + str(self.__args.dispatch)) console_log("Dispatch Selection: " + str(self.__args.dispatch))
if self.__args.ipblocks == None: if self.__args.ipblocks == None:
logging.info("IP Blocks: All") console_log("IP Blocks: All")
else: else:
logging.info("IP Blocks: " + str(self.__args.ipblocks)) console_log("IP Blocks: "+ str(self.__args.ipblocks))
if self.__args.kernel_verbose > 5: if self.__args.kernel_verbose > 5:
logging.info("KernelName verbose: DISABLED") console_log("KernelName verbose: DISABLED")
else: else:
logging.info("KernelName verbose: " + str(self.__args.kernel_verbose)) console_log("KernelName verbose: " + str(self.__args.kernel_verbose))
print_status("Collecting Performance Counters")
# Run profiling on each input file
input_files = glob.glob(self.get_args().path + "/perfmon/*.txt") input_files = glob.glob(self.get_args().path + "/perfmon/*.txt")
input_files.sort() input_files.sort()
# Run profiling on each input file
for fname in input_files: for fname in input_files:
# Kernel filtering (in-place replacement) # Kernel filtering (in-place replacement)
if not self.__args.kernel == None: if not self.__args.kernel == None:
@@ -345,9 +336,9 @@ class OmniProfiler_Base:
) )
# log output from profile filtering # log output from profile filtering
if not success: if not success:
error(output) console_error(output)
else: else:
logging.debug(output) console_error(output)
# Dispatch filtering (inplace replacement) # Dispatch filtering (inplace replacement)
if not self.__args.dispatch == None: if not self.__args.dispatch == None:
@@ -365,11 +356,14 @@ class OmniProfiler_Base:
) )
# log output from profile filtering # log output from profile filtering
if not success: if not success:
error(output) console_error(output)
else: else:
logging.debug(output) console_debug(output)
logging.info("\nCurrent input file: %s" % fname) console_log(
"profile",
"Current input file: %s" % fname
)
# Fetch any SoC/profiler specific profiling options # Fetch any SoC/profiler specific profiling options
options = self._soc.get_profiler_options() options = self._soc.get_profiler_options()
options += self.get_profiler_options(fname) options += self.get_profiler_options(fname)
@@ -385,15 +379,18 @@ class OmniProfiler_Base:
elif self.__profiler == "rocscope": elif self.__profiler == "rocscope":
run_rocscope(self.__args, fname) run_rocscope(self.__args, fname)
else: else:
# TODO: Finish logic #TODO: Finish logic
error("profiler not supported") console_error("Profiler not supported")
@abstractmethod @abstractmethod
def post_processing(self): def post_processing(self):
"""Perform any post-processing steps prior to profiling.""" """Perform any post-processing steps prior to profiling.
logging.debug( """
"[profiling] performing post-processing using %s profiler" % self.__profiler console_debug(
"profiling",
"performing post-processing using %s profiler" % self.__profiler
) )
gen_sysinfo( gen_sysinfo(
workload_name=self.__args.name, workload_name=self.__args.name,
workload_dir=self.get_args().path, workload_dir=self.get_args().path,
@@ -22,11 +22,10 @@
# SOFTWARE. # SOFTWARE.
##############################################################################el ##############################################################################el
import logging
import os import os
from omniperf_profile.profiler_base import OmniProfiler_Base from omniperf_profile.profiler_base import OmniProfiler_Base
from utils.utils import demarcate, replace_timestamps from utils.utils import demarcate, replace_timestamps, console_log
from utils.kernel_name_shortener import kernel_name_shortener from utils.kernel_name_shortener import kernel_name_shortener
@@ -69,12 +68,18 @@ class rocprof_v1_profiler(OmniProfiler_Base):
"""Run profiling.""" """Run profiling."""
if self.ready_to_profile: if self.ready_to_profile:
if self.get_args().roof_only: if self.get_args().roof_only:
logging.info("[roofline] Generating pmc_perf.csv") console_log(
"roofline",
"Generating pmc_perf.csv (roofline counters only)."
)
# Log profiling options and setup filtering # Log profiling options and setup filtering
super().run_profiling(version, prog) super().run_profiling(version, prog)
else: else:
logging.info("[roofline] Detected existing pmc_perf.csv") console_log(
"roofline",
"Detected existing pmc_perf.csv"
)
@demarcate @demarcate
def post_processing(self): def post_processing(self):
"""Perform any post-processing steps prior to profiling.""" """Perform any post-processing steps prior to profiling."""
@@ -23,9 +23,8 @@
##############################################################################el ##############################################################################el
import os import os
import logging
from omniperf_profile.profiler_base import OmniProfiler_Base from omniperf_profile.profiler_base import OmniProfiler_Base
from utils.utils import demarcate from utils.utils import demarcate, console_log
from utils.kernel_name_shortener import kernel_name_shortener from utils.kernel_name_shortener import kernel_name_shortener
@@ -68,10 +67,17 @@ class rocprof_v2_profiler(OmniProfiler_Base):
"""Run profiling.""" """Run profiling."""
if self.ready_to_profile: if self.ready_to_profile:
if self.get_args().roof_only: if self.get_args().roof_only:
logging.info("[roofline] Generating pmc_perf.csv") console_log(
"roofline",
"Generating pmc_perf.csv (roofline counters only)."
)
# Log profiling options and setup filtering
super().run_profiling(version, prog) super().run_profiling(version, prog)
else: else:
logging.info("[roofline] Detected existing pmc_perf.csv") console_log(
"roofline",
"Detected existing pmc_perf.csv"
)
@demarcate @demarcate
def post_processing(self): def post_processing(self):
@@ -22,9 +22,8 @@
# SOFTWARE. # SOFTWARE.
##############################################################################el ##############################################################################el
import logging
from omniperf_profile.profiler_base import OmniProfiler_Base from omniperf_profile.profiler_base import OmniProfiler_Base
from utils.utils import demarcate from utils.utils import demarcate, console_log
class rocscope_profiler(OmniProfiler_Base): class rocscope_profiler(OmniProfiler_Base):
@@ -36,20 +35,29 @@ class rocscope_profiler(OmniProfiler_Base):
# ----------------------- # -----------------------
@demarcate @demarcate
def pre_processing(self): def pre_processing(self):
"""Perform any pre-processing steps prior to profiling.""" """Perform any pre-processing steps prior to profiling.
self.__profiler = "rocscope" """
logging.debug("[profiling] pre-processing using %s profiler" % self.__profiler) self.__profiler="rocscope"
console_log(
"profiling",
"pre-processing using %s profiler" % self.__profiler
)
#TODO: Finish implementation
@demarcate @demarcate
def run_profiling(self, version, prog): def run_profiling(self, version, prog):
"""Run profiling.""" """Run profiling.
logging.debug( """
"[profiling] performing profiling using %s profiler" % self.__profiler console_log(
"profiling"
"performing profiling using %s profiler" % self.__profiler
) )
#TODO: Finish implementation
@demarcate @demarcate
def post_processing(self): def post_processing(self):
"""Perform any post-processing steps prior to profiling.""" """Perform any post-processing steps prior to profiling.
logging.debug( """
"[profiling] performing post-processing using %s profiler" % self.__profiler console_log(
"profiling"
"performing post-processing using %s profiler" % self.__profiler
) )
#TODO: Finish implementation
@@ -23,14 +23,13 @@
##############################################################################el ##############################################################################el
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import logging
import os import os
import math import math
import shutil import shutil
import glob import glob
import re import re
import numpy as np import numpy as np
from utils.utils import demarcate from utils.utils import demarcate, console_debug, console_log
from pathlib import Path from pathlib import Path
from omniperf_base import SUPPORTED_ARCHS from omniperf_base import SUPPORTED_ARCHS
@@ -229,9 +228,9 @@ class OmniSoC_Base:
ip = re.match(mpattern, fbase).group(1) ip = re.match(mpattern, fbase).group(1)
if ip in self.__args.ipblocks: if ip in self.__args.ipblocks:
pmc_files_list.append(fname) pmc_files_list.append(fname)
logging.info("fname: " + fbase + ": Added") console_log("fname: " + fbase + ": Added")
else: else:
logging.info("fname: " + fbase + ": Skipped") console_log("fname: " + fbase + ": Skipped")
else: else:
# default: take all perfmons # default: take all perfmons
@@ -251,19 +250,32 @@ class OmniSoC_Base:
# ---------------------------------------------------- # ----------------------------------------------------
@abstractmethod @abstractmethod
def profiling_setup(self): def profiling_setup(self):
"""Perform any SoC-specific setup prior to profiling.""" """Perform any SoC-specific setup prior to profiling.
logging.debug("[profiling] perform SoC profiling setup for %s" % self.__arch) """
console_debug(
"profiling",
"perform SoC profiling setup for %s" % self.__arch
)
@abstractmethod @abstractmethod
def post_profiling(self): def post_profiling(self):
"""Perform any SoC-specific post profiling activities.""" """Perform any SoC-specific post profiling activities.
logging.debug("[profiling] perform SoC post processing for %s" % self.__arch) """
console_debug(
"profiling",
"perform SoC post processing for %s" % self.__arch
)
@abstractmethod @abstractmethod
def analysis_setup(self): def analysis_setup(self):
"""Perform any SoC-specific setup prior to analysis.""" """Perform any SoC-specific setup prior to analysis.
logging.debug("[analysis] perform SoC analysis setup for %s" % self.__arch) """
console_debug(
"analysis",
"perform SoC analysis setup for %s" % self.__arch
)
@demarcate @demarcate
def perfmon_coalesce(pmc_files_list, perfmon_config, workload_dir): def perfmon_coalesce(pmc_files_list, perfmon_config, workload_dir):
@@ -25,7 +25,7 @@
import os import os
import config import config
from omniperf_soc.soc_base import OmniSoC_Base from omniperf_soc.soc_base import OmniSoC_Base
from utils.utils import demarcate, error from utils.utils import demarcate, console_error
class gfx906_soc(OmniSoC_Base): class gfx906_soc(OmniSoC_Base):
@@ -71,7 +71,7 @@ class gfx906_soc(OmniSoC_Base):
"""Perform any SoC-specific setup prior to profiling.""" """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup() super().profiling_setup()
if self.get_args().roof_only: if self.get_args().roof_only:
error("%s does not support roofline analysis" % self.get_arch()) console_error("%s does not support roofline analysis" % self.get_arch())
# Perfmon filtering # Perfmon filtering
self.perfmon_filter() self.perfmon_filter()
@@ -25,7 +25,7 @@
import os import os
import config import config
from omniperf_soc.soc_base import OmniSoC_Base from omniperf_soc.soc_base import OmniSoC_Base
from utils.utils import demarcate, error from utils.utils import demarcate, console_error
class gfx908_soc(OmniSoC_Base): class gfx908_soc(OmniSoC_Base):
@@ -79,7 +79,7 @@ class gfx908_soc(OmniSoC_Base):
"""Perform any SoC-specific setup prior to profiling.""" """Perform any SoC-specific setup prior to profiling."""
super().profiling_setup() super().profiling_setup()
if self.get_args().roof_only: if self.get_args().roof_only:
error("%s does not support roofline analysis" % self.get_arch()) console_error("%s does not support roofline analysis" % self.get_arch())
# Perfmon filtering # Perfmon filtering
self.perfmon_filter(self.get_args().roof_only) self.perfmon_filter(self.get_args().roof_only)
@@ -25,9 +25,8 @@
import os import os
import config import config
from omniperf_soc.soc_base import OmniSoC_Base from omniperf_soc.soc_base import OmniSoC_Base
from utils.utils import demarcate, mibench from utils.utils import demarcate, mibench, console_log
from roofline import Roofline from roofline import Roofline
import logging
class gfx90a_soc(OmniSoC_Base): class gfx90a_soc(OmniSoC_Base):
@@ -90,15 +89,20 @@ class gfx90a_soc(OmniSoC_Base):
def post_profiling(self): def post_profiling(self):
"""Perform any SoC-specific post profiling activities.""" """Perform any SoC-specific post profiling activities."""
super().post_profiling() super().post_profiling()
if not self.get_args().no_roof: if not self.get_args().no_roof:
logging.info( console_log(
"[roofline] Checking for roofline.csv in " + str(self.get_args().path) "roofline",
"Checking for roofline.csv in " + str(self.get_args().path)
) )
if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")): if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")):
mibench(self.get_args(), self._mspec) mibench(self.get_args(), self._mspec)
self.roofline_obj.post_processing() self.roofline_obj.post_processing()
else: else:
logging.info("[roofline] Skipping roofline") console_log(
"roofline",
"Skipping roofline"
)
@demarcate @demarcate
def analysis_setup(self, roofline_parameters=None): def analysis_setup(self, roofline_parameters=None):
@@ -25,9 +25,8 @@
import os import os
import config import config
from omniperf_soc.soc_base import OmniSoC_Base from omniperf_soc.soc_base import OmniSoC_Base
from utils.utils import demarcate, mibench from utils.utils import demarcate, mibench, console_log
from roofline import Roofline from roofline import Roofline
import logging
class gfx940_soc(OmniSoC_Base): class gfx940_soc(OmniSoC_Base):
@@ -89,7 +88,10 @@ class gfx940_soc(OmniSoC_Base):
"""Perform any SoC-specific post profiling activities.""" """Perform any SoC-specific post profiling activities."""
super().post_profiling() super().post_profiling()
logging.info("[roofline] Roofline temporarily disabled in Mi300") console_log(
"roofline",
"Roofline temporarily disabled in Mi300"
)
# if not self.get_args().no_roof: # if not self.get_args().no_roof:
# logging.info("[roofline] Checking for roofline.csv in " + str(self.get_args().path)) # logging.info("[roofline] Checking for roofline.csv in " + str(self.get_args().path))
# if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")): # if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")):
@@ -102,7 +104,10 @@ class gfx940_soc(OmniSoC_Base):
def analysis_setup(self, roofline_parameters=None): def analysis_setup(self, roofline_parameters=None):
"""Perform any SoC-specific setup prior to analysis.""" """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup() super().analysis_setup()
logging.info("[roofline] Roofline temporarily disabled in Mi300") console_log(
"roofline",
"Roofline temporarily disabled in Mi300"
)
# configure roofline for analysis # configure roofline for analysis
# if roofline_parameters: # if roofline_parameters:
# self.roofline_obj = Roofline(self.get_args(), roofline_parameters) # self.roofline_obj = Roofline(self.get_args(), roofline_parameters)
@@ -25,9 +25,8 @@
import os import os
import config import config
from omniperf_soc.soc_base import OmniSoC_Base from omniperf_soc.soc_base import OmniSoC_Base
from utils.utils import demarcate, mibench from utils.utils import demarcate, mibench, console_log
from roofline import Roofline from roofline import Roofline
import logging
class gfx941_soc(OmniSoC_Base): class gfx941_soc(OmniSoC_Base):
@@ -89,7 +88,10 @@ class gfx941_soc(OmniSoC_Base):
"""Perform any SoC-specific post profiling activities.""" """Perform any SoC-specific post profiling activities."""
super().post_profiling() super().post_profiling()
logging.info("[roofline] Roofline temporarily disabled in Mi300") console_log(
"roofline",
"Roofline temporarily disabled in Mi300"
)
# if not self.get_args().no_roof: # if not self.get_args().no_roof:
# logging.info("[roofline] Checking for roofline.csv in " + str(self.get_args().path)) # logging.info("[roofline] Checking for roofline.csv in " + str(self.get_args().path))
# if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")): # if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")):
@@ -102,7 +104,10 @@ class gfx941_soc(OmniSoC_Base):
def analysis_setup(self, roofline_parameters=None): def analysis_setup(self, roofline_parameters=None):
"""Perform any SoC-specific setup prior to analysis.""" """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup() super().analysis_setup()
logging.info("[roofline] Roofline temporarily disabled in Mi300") console_log(
"roofline",
"Roofline temporarily disabled in Mi300"
)
# configure roofline for analysis # configure roofline for analysis
# if roofline_parameters: # if roofline_parameters:
# self.roofline_obj = Roofline(self.get_args(), roofline_parameters) # self.roofline_obj = Roofline(self.get_args(), roofline_parameters)
@@ -25,9 +25,8 @@
import os import os
import config import config
from omniperf_soc.soc_base import OmniSoC_Base from omniperf_soc.soc_base import OmniSoC_Base
from utils.utils import demarcate, mibench from utils.utils import demarcate, mibench, console_log
from roofline import Roofline from roofline import Roofline
import logging
class gfx942_soc(OmniSoC_Base): class gfx942_soc(OmniSoC_Base):
@@ -89,7 +88,10 @@ class gfx942_soc(OmniSoC_Base):
"""Perform any SoC-specific post profiling activities.""" """Perform any SoC-specific post profiling activities."""
super().post_profiling() super().post_profiling()
logging.info("[roofline] Roofline temporarily disabled in Mi300") console_log(
"roofline",
"Roofline temporarily disabled in Mi300"
)
# if not self.get_args().no_roof: # if not self.get_args().no_roof:
# logging.info("[roofline] Checking for roofline.csv in " + str(self.get_args().path)) # logging.info("[roofline] Checking for roofline.csv in " + str(self.get_args().path))
# if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")): # if not os.path.isfile(os.path.join(self.get_args().path, "roofline.csv")):
@@ -102,7 +104,10 @@ class gfx942_soc(OmniSoC_Base):
def analysis_setup(self, roofline_parameters=None): def analysis_setup(self, roofline_parameters=None):
"""Perform any SoC-specific setup prior to analysis.""" """Perform any SoC-specific setup prior to analysis."""
super().analysis_setup() super().analysis_setup()
logging.info("[roofline] Roofline temporarily disabled in Mi300") console_log(
"roofline",
"Roofline temporarily disabled in Mi300"
)
# configure roofline for analysis # configure roofline for analysis
# if roofline_parameters: # if roofline_parameters:
# self.roofline_obj = Roofline(self.get_args(), roofline_parameters) # self.roofline_obj = Roofline(self.get_args(), roofline_parameters)
+47 -32
View File
@@ -23,12 +23,11 @@
##############################################################################el ##############################################################################el
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import logging
import os import os
import sys import sys
import time import time
from dash import dcc from dash import dcc
from utils.utils import mibench, gen_sysinfo, demarcate, error from utils.utils import mibench, gen_sysinfo, demarcate, console_error, console_log, console_debug
from dash import html from dash import html
import plotly.graph_objects as go import plotly.graph_objects as go
from utils.roofline_calc import calc_ai, constuct_roof from utils.roofline_calc import calc_ai, constuct_roof
@@ -77,10 +76,8 @@ class Roofline:
self.validate_parameters() self.validate_parameters()
def validate_parameters(self): def validate_parameters(self):
if self.__run_parameters["include_kernel_names"] and ( if self.__run_parameters['include_kernel_names'] and (not self.__run_parameters['is_standalone']):
not self.__run_parameters["is_standalone"] console_error("--roof-only is required for --kernel-names")
):
error("--roof-only is required for --kernel-names")
def roof_setup(self): def roof_setup(self):
# set default workload path if not specified # set default workload path if not specified
@@ -103,13 +100,16 @@ class Roofline:
): ):
"""Generate a set of empirical roofline plots given a directory containing required profiling and benchmarking data""" """Generate a set of empirical roofline plots given a directory containing required profiling and benchmarking data"""
# Create arithmetic intensity data that will populate the roofline model # Create arithmetic intensity data that will populate the roofline model
logging.debug("[roofline] Path: %s" % self.__run_parameters["workload_dir"]) console_debug(
self.__ai_data = calc_ai(self.__run_parameters["sort_type"], ret_df) "roofline",
"Path: %s" % self.__run_parameters['workload_dir']
logging.debug("[roofline] AI at each mem level:") )
self.__ai_data = calc_ai(self.__run_parameters['sort_type'], ret_df)
msg="AI at each mem level:"
for i in self.__ai_data: for i in self.__ai_data:
logging.debug("%s -> %s" % (i, self.__ai_data[i])) msg += ("\n\t%s -> %s" % (i, self.__ai_data[i]))
logging.debug("\n") console_debug(msg)
# Generate a roofline figure for each data type # Generate a roofline figure for each data type
fp32_fig = self.generate_plot(dtype="FP32") fp32_fig = self.generate_plot(dtype="FP32")
@@ -166,11 +166,12 @@ class Roofline:
self.__run_parameters["workload_dir"] self.__run_parameters["workload_dir"]
+ "/empirRoof_gpu-{}_int8_fp16.pdf".format(dev_id) + "/empirRoof_gpu-{}_int8_fp16.pdf".format(dev_id)
) )
if self.__run_parameters["include_kernel_names"]: if self.__run_parameters['include_kernel_names']:
self.__figure.write_image( self.__figure.write_image(self.__run_parameters['workload_dir'] + "/kernelName_legend.pdf")
self.__run_parameters["workload_dir"] + "/kernelName_legend.pdf" console_log(
) "roofline",
logging.info("[roofline] Empirical Roofline PDFs saved!") "Empirical Roofline PDFs saved!"
)
else: else:
return html.Section( return html.Section(
id="roofline", id="roofline",
@@ -211,7 +212,10 @@ class Roofline:
roofline_parameters=self.__run_parameters, roofline_parameters=self.__run_parameters,
dtype=dtype, dtype=dtype,
) )
logging.debug("[roofline] Ceiling data:\n%s" % self.__ceiling_data) console_debug(
"roofline",
"Ceiling data:\n%s" % self.__ceiling_data
)
####################### #######################
# Plot ceilings # Plot ceilings
@@ -359,8 +363,10 @@ class Roofline:
app_path = os.path.join(self.__run_parameters["workload_dir"], "pmc_perf.csv") app_path = os.path.join(self.__run_parameters["workload_dir"], "pmc_perf.csv")
roofline_exists = os.path.isfile(app_path) roofline_exists = os.path.isfile(app_path)
if not roofline_exists: if not roofline_exists:
logging.error("[roofline] Error: {} does not exist".format(app_path)) console_error(
sys.exit(1) "roofline",
"{} does not exist".format(app_path)
)
t_df = OrderedDict() t_df = OrderedDict()
t_df["pmc_perf"] = pd.read_csv(app_path) t_df["pmc_perf"] = pd.read_csv(app_path)
self.empirical_roofline(ret_df=t_df) self.empirical_roofline(ret_df=t_df)
@@ -370,12 +376,12 @@ class Roofline:
def pre_processing(self): def pre_processing(self):
if self.__args.roof_only: if self.__args.roof_only:
# check for sysinfo # check for sysinfo
logging.info( console_log(
"[roofline] Checking for sysinfo.csv in " + str(self.__args.path) "roofline", "Checking for sysinfo.csv in " + str(self.__args.path)
) )
sysinfo_path = os.path.join(self.__args.path, "sysinfo.csv") sysinfo_path = os.path.join(self.__args.path, "sysinfo.csv")
if not os.path.isfile(sysinfo_path): if not os.path.isfile(sysinfo_path):
logging.info("[roofline] sysinfo.csv not found. Generating...") console_log("roofline", "sysinfo.csv not found. Generating...")
class Dummy_SoC: class Dummy_SoC:
roofline_obj = True roofline_obj = True
@@ -395,28 +401,37 @@ class Roofline:
def profile(self): def profile(self):
if self.__args.roof_only: if self.__args.roof_only:
# check for roofline benchmark # check for roofline benchmark
logging.info( console_log(
"[roofline] Checking for roofline.csv in " + str(self.__args.path) "roofline",
"Checking for roofline.csv in " + str(self.__args.path)
) )
roof_path = os.path.join(self.__args.path, "roofline.csv") roof_path = os.path.join(self.__args.path, "roofline.csv")
if not os.path.isfile(roof_path): if not os.path.isfile(roof_path):
mibench(self.__args, self.__mspec) mibench(self.__args, self.__mspec)
# check for profiling data # check for profiling data
logging.info( console_log(
"[roofline] Checking for pmc_perf.csv in " + str(self.__args.path) "roofline",
"Checking for pmc_perf.csv in " + str(self.__args.path)
) )
app_path = os.path.join(self.__args.path, "pmc_perf.csv") app_path = os.path.join(self.__args.path, "pmc_perf.csv")
if not os.path.isfile(app_path): if not os.path.isfile(app_path):
logging.info("[roofline] pmc_perf.csv not found. Generating...") console_log(
"roofline",
"pmc_perf.csv not found. Generating..."
)
if not self.__args.remaining: if not self.__args.remaining:
error( console_error(
"profiling"
"An <app_cmd> is required to run.\nomniperf profile -n test -- <app_cmd>" "An <app_cmd> is required to run.\nomniperf profile -n test -- <app_cmd>"
) )
# TODO: Add an equivelent of characterize_app() to run profiling directly out of this module #TODO: Add an equivelent of characterize_app() to run profiling directly out of this module
elif self.__args.no_roof: elif self.__args.no_roof:
logging.info("[roofline] Skipping roofline.") console_log(
"roofline",
"Skipping roofline."
)
else: else:
mibench(self.__args, self.__mspec) mibench(self.__args, self.__mspec)
@@ -23,12 +23,11 @@
##############################################################################el ##############################################################################el
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from utils.utils import error, is_workload_empty, demarcate from utils.utils import is_workload_empty, demarcate, console_error, console_log, console_warning, console_debug
from pymongo import MongoClient from pymongo import MongoClient
from tqdm import tqdm from tqdm import tqdm
import os import os
import logging
import getpass import getpass
import pandas as pd import pandas as pd
@@ -63,7 +62,7 @@ class DatabaseConnector:
soc = sys_info["name"][0] soc = sys_info["name"][0]
name = sys_info["workload_name"][0] name = sys_info["workload_name"][0]
else: else:
error("[database] Unable to parse SoC and/or workload name from sysinfo.csv") console_error("[database] Unable to parse SoC and/or workload name from sysinfo.csv")
self.connection_info["db"] = ( self.connection_info["db"] = (
"omniperf_" + str(self.args.team) + "_" + str(name) + "_" + str(soc) "omniperf_" + str(self.args.team) + "_" + str(name) + "_" + str(soc)
@@ -76,10 +75,9 @@ class DatabaseConnector:
file = "blank" file = "blank"
for file in tqdm(os.listdir(self.connection_info["workload"])): for file in tqdm(os.listdir(self.connection_info["workload"])):
if file.endswith(".csv"): if file.endswith(".csv"):
logging.info( console_log(
"[database] Uploading: %s" % self.connection_info["workload"] "database",
+ "/" "Uploading: %s" % self.connection_info["workload"] + "/" + file
+ file
) )
try: try:
fileName = file[0 : file.find(".")] fileName = file[0 : file.find(".")]
@@ -97,15 +95,21 @@ class DatabaseConnector:
os.system(cmd) os.system(cmd)
i += 1 i += 1
except pd.errors.EmptyDataError: except pd.errors.EmptyDataError:
logging.info("[database] Skipping empty file: %s" % file) console_warning("[database] Skipping empty file: %s" % file)
logging.info("[database] %s collections successfully added." % i) console_log(
"database",
"%s collections successfully added." % i
)
mydb = self.client["workload_names"] mydb = self.client["workload_names"]
mycol = mydb["names"] mycol = mydb["names"]
value = {"name": self.connection_info["db"]} value = {"name": self.connection_info["db"]}
newValue = {"name": self.connection_info["db"]} newValue = {"name": self.connection_info["db"]}
mycol.replace_one(value, newValue, upsert=True) mycol.replace_one(value, newValue, upsert=True)
logging.info("[database] Workload name uploaded.") console_log(
"database",
"Workload name uploaded."
)
@demarcate @demarcate
def db_remove(self): def db_remove(self):
@@ -116,63 +120,60 @@ class DatabaseConnector:
self.client.drop_database(db_to_remove) self.client.drop_database(db_to_remove)
db = self.client["workload_names"] db = self.client["workload_names"]
col = db["names"] col = db["names"]
col.delete_many({"name": self.connection_info["workload"]}) col.delete_many({"name": self.connection_info['workload']})
logging.info( console_log(
"[database] Successfully removed %s" % self.connection_info["workload"] "database",
"Successfully removed %s" % self.connection_info['workload']
) )
@abstractmethod @abstractmethod
def pre_processing(self): def pre_processing(self):
"""Perform any pre-processing steps prior to database conncetion.""" """Perform any pre-processing steps prior to database conncetion.
logging.debug("[database] pre-processing database connection") """
console_debug(
"database",
"pre-processing database connection"
)
if not self.args.remove and not self.args.upload: if not self.args.remove and not self.args.upload:
error("Either -i/--import or -r/--remove is required in database mode") console_error("Either -i/--import or -r/--remove is required in database mode")
self.interaction_type = "import" if self.args.upload else "remove" self.interaction_type = 'import' if self.args.upload else 'remove'
# Detect interaction type # Detect interaction type
if self.interaction_type == "remove": if self.interaction_type == 'remove':
logging.debug("[database] validating arguments for --remove workflow") console_debug(
"database",
"validating arguments for --remove workflow"
)
is_full_workload_name = self.args.workload.count("_") >= 3 is_full_workload_name = self.args.workload.count("_") >= 3
if not is_full_workload_name: if not is_full_workload_name:
error( console_error("-w/--workload is not valid. Please use full workload name as seen in GUI when removing (i.e. omniperf_asw_vcopy_mi200)")
"-w/--workload is not valid. Please use full workload name as seen in GUI when removing (i.e. omniperf_asw_vcopy_mi200)" if self.connection_info['host'] == None or self.connection_info['username'] == None:
) console_error("-H/--host and -u/--username are required when interaction type is set to %s" % self.interaction_type)
if self.connection_info['workload'] == "admin" or self.connection_info['workload'] == "local":
if ( console_error("Cannot remove %s. Try again." % self.connection_info['workload'])
self.connection_info["host"] == None
or self.connection_info["username"] == None
):
error(
"-H/--host and -u/--username are required when interaction type is set to %s"
% self.interaction_type
)
if (
self.connection_info["workload"] == "admin"
or self.connection_info["workload"] == "local"
):
error("Cannot remove %s. Try again." % self.connection_info["workload"])
else: else:
logging.debug("[database] validating arguments for --import workflow") console_debug(
"database",
"validating arguments for --import workflow"
)
if ( if (
self.connection_info["host"] == None self.connection_info["host"] == None
or self.connection_info["team"] == None or self.connection_info["team"] == None
or self.connection_info["username"] == None or self.connection_info["username"] == None
or self.connection_info["workload"] == None or self.connection_info["workload"] == None
): ):
error( console_error("-H/--host, -w/--workload, -u/--username, and -t/--team are all required when interaction type is set to %s" % self.interaction_type)
"-H/--host, -w/--workload, -u/--username, and -t/--team are all required when interaction type is set to %s"
% self.interaction_type
)
if os.path.isdir(os.path.abspath(self.connection_info["workload"])): if os.path.isdir(os.path.abspath(self.connection_info["workload"])):
is_workload_empty(self.connection_info["workload"]) is_workload_empty(self.connection_info["workload"])
else: else:
error("--workload is invalid. Please pass path to a valid directory.") console_error("--workload is invalid. Please pass path to a valid directory.")
if len(self.args.team) > 13: if len(self.args.team) > 13:
error("--team exceeds 13 character limit. Try again.") console_error("--team exceeds 13 character limit. Try again.")
# format path properly # format path properly
self.connection_info["workload"] = os.path.abspath( self.connection_info["workload"] = os.path.abspath(
self.connection_info["workload"] self.connection_info["workload"]
@@ -183,9 +184,15 @@ class DatabaseConnector:
try: try:
self.connection_info["password"] = getpass.getpass() self.connection_info["password"] = getpass.getpass()
except Exception as e: except Exception as e:
error("[database] PASSWORD ERROR %s" % e) console_error(
"database",
"PASSWORD ERROR %s" % e
)
else: else:
logging.info("[database] Password recieved") console_log(
"database",
"Password recieved"
)
else: else:
password = self.connection_info["password"] password = self.connection_info["password"]
@@ -207,4 +214,10 @@ class DatabaseConnector:
try: try:
self.client.server_info() self.client.server_info()
except: except:
error("[database] Unable to connect to the DB server.") console_error(
"database",
"Unable to connect to the DB server."
)
@@ -33,8 +33,8 @@ import collections
from collections import OrderedDict from collections import OrderedDict
from pathlib import Path from pathlib import Path
from utils import schema from utils import schema
from utils.utils import console_debug, console_error
import config import config
import logging
# TODO: use pandas chunksize or dask to read really large csv file # TODO: use pandas chunksize or dask to read really large csv file
# from dask import dataframe as dd # from dask import dataframe as dd
@@ -173,9 +173,8 @@ def create_df_pmc(raw_data_dir, verbose):
dfs.append(tmp_df) dfs.append(tmp_df)
coll_levels.append(f[:-4]) coll_levels.append(f[:-4])
final_df = pd.concat(dfs, keys=coll_levels, axis=1, copy=False) final_df = pd.concat(dfs, keys=coll_levels, axis=1, copy=False)
# TODO: join instead of concat!
if verbose >= 2: if verbose >= 2:
print("pmc_raw_data final_df ", final_df.info()) console_debug("pmc_raw_data final_df $s" % final_df.info())
return final_df return final_df
@@ -231,5 +230,4 @@ def is_single_panel_config(root_dir, supported_archs):
elif counter == len(supported_archs): elif counter == len(supported_archs):
return False return False
else: else:
logging.error("Found multiple panel config sets but incomplete for all archs!") console_error("Found multiple panel config sets but incomplete for all archs.")
sys.exit(1)
@@ -29,6 +29,7 @@ import plotly.express as px
import colorlover import colorlover
from utils import schema from utils import schema
from utils.utils import console_error
pd.set_option( pd.set_option(
"mode.chained_assignment", None "mode.chained_assignment", None
@@ -243,12 +244,7 @@ def build_bar_chart(display_df, table_config, barchart_elements, norm_filt):
).update_xaxes(range=[0, 110]) ).update_xaxes(range=[0, 110])
) )
else: else:
print( console_error("Table id %s. Cannot determine barchart type." % table_config["id"])
"ERROR: Table id {}. Cannot determine barchart type.".format(
table_config["id"]
)
)
sys.exit(-1)
# update layout for each of the charts # update layout for each of the charts
for fig in d_figs: for fig in d_figs:
@@ -26,14 +26,14 @@ import sys
from dash import html from dash import html
from dash_svg import Svg, G, Path, Rect, Text from dash_svg import Svg, G, Path, Rect, Text
from utils.utils import console_error
hidden_columns = ["Tips", "coll_level"] hidden_columns = ["Tips", "coll_level"]
def insert_chart_data(mem_data, base_data): def insert_chart_data(mem_data, base_data):
if len(mem_data) != 1: if len(mem_data) != 1:
print("Memory Chart config doesn't follow expected formatting") console_error("Memory Chart config doesn't follow expected formatting")
sys.exit(1)
table_config = mem_data[0]["metric_table"] table_config = mem_data[0]["metric_table"]
@@ -23,14 +23,12 @@
##############################################################################el ##############################################################################el
import os import os
import sys import glob
import logging
import glob
import re import re
import subprocess import subprocess
import pandas as pd import pandas as pd
from utils.utils import error from utils.utils import console_error, console_debug, console_log
cache = dict() cache = dict()
@@ -123,7 +121,7 @@ def kernel_name_shortener(workload_dir, level):
if level < 5: if level < 5:
cpp_filt = os.path.join("/usr", "bin", "c++filt") cpp_filt = os.path.join("/usr", "bin", "c++filt")
if not os.path.isfile(cpp_filt): if not os.path.isfile(cpp_filt):
error("Could not resolve c++filt in expected directory: %s" % cpp_filt) console_error("Could not resolve c++filt in expected directory: %s" % cpp_filt)
for fpath in glob.glob(workload_dir + "/[SQpmc]*.csv"): for fpath in glob.glob(workload_dir + "/[SQpmc]*.csv"):
try: try:
@@ -135,8 +133,12 @@ def kernel_name_shortener(workload_dir, level):
modified_df = shorten_file(orig_df, level) modified_df = shorten_file(orig_df, level)
modified_df.to_csv(fpath, index=False) modified_df.to_csv(fpath, index=False)
except pd.errors.EmptyDataError: except pd.errors.EmptyDataError:
logging.debug( console_debug(
"[profiling] Skipping shortening on empty csv: %s" % str(fpath) "profiling",
"Skipping shortening on empty csv: %s" % str(fpath)
) )
logging.info("[profiling] Kernel_Name shortening complete.") console_log(
"profiling",
"Kernel_Name shortening complete."
)
@@ -27,13 +27,12 @@ import sys
import astunparse import astunparse
import re import re
import os import os
import warnings
import pandas as pd import pandas as pd
import numpy as np import numpy as np
from utils import schema from utils import schema
from utils.utils import error from utils.utils import console_warning, console_error
from pathlib import Path from pathlib import Path
import logging
import warnings
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Internal global definitions # Internal global definitions
@@ -420,8 +419,7 @@ def calc_builtin_var(var, sys_info):
elif isinstance(var, str) and var.startswith("$total_l2_chan"): elif isinstance(var, str) and var.startswith("$total_l2_chan"):
return sys_info.total_l2_chan return sys_info.total_l2_chan
else: else:
print("Don't support", var) console_error("Built-in var \" %s \" is not supported" % var)
sys.exit(1)
def build_dfs(archConfigs, filter_metrics, sys_info): def build_dfs(archConfigs, filter_metrics, sys_info):
@@ -679,7 +677,8 @@ def eval_metric(dfs, dfs_type, sys_info, raw_pmc_df, debug):
and hasattr(raw_pmc_df["pmc_perf"], "GRBM_GUI_ACTIVE") and hasattr(raw_pmc_df["pmc_perf"], "GRBM_GUI_ACTIVE")
and (raw_pmc_df["pmc_perf"]["GRBM_GUI_ACTIVE"] == 0).any() and (raw_pmc_df["pmc_perf"]["GRBM_GUI_ACTIVE"] == 0).any()
): ):
error("Dectected GRBM_GUI_ACTIVE == 0\nHaulting execution.") console_warning("Dectected GRBM_GUI_ACTIVE == 0")
console_error("Hauting execution for warning above.")
ammolite__se_per_gpu = sys_info.se_per_gpu ammolite__se_per_gpu = sys_info.se_per_gpu
ammolite__pipes_per_gpu = sys_info.pipes_per_gpu ammolite__pipes_per_gpu = sys_info.pipes_per_gpu
@@ -859,7 +858,7 @@ def apply_filters(workload, dir, is_gui, debug):
kernels_df = pd.read_csv(os.path.join(dir, "pmc_kernel_top.csv")) kernels_df = pd.read_csv(os.path.join(dir, "pmc_kernel_top.csv"))
for kernel_id in workload.filter_kernel_ids: for kernel_id in workload.filter_kernel_ids:
if kernel_id >= len(kernels_df["Kernel_Name"]): if kernel_id >= len(kernels_df["Kernel_Name"]):
error( console_error(
"{} is an invalid kernel id. Please enter an id between 0-{}".format( "{} is an invalid kernel id. Please enter an id between 0-{}".format(
kernel_id, len(kernels_df["Kernel_Name"]) - 1 kernel_id, len(kernels_df["Kernel_Name"]) - 1
) )
@@ -885,7 +884,7 @@ def apply_filters(workload, dir, is_gui, debug):
) )
ret_df = ret_df.loc[df_cleaned.isin(workload.filter_kernel_ids)] ret_df = ret_df.loc[df_cleaned.isin(workload.filter_kernel_ids)]
else: else:
error("Mixing kernel indices and string filters is not currently supported") console_error("analyze", "Mixing kernel indices and string filters is not currently supported")
if workload.filter_dispatch_ids: if workload.filter_dispatch_ids:
# NB: support ignoring the 1st n dispatched execution by '> n' # NB: support ignoring the 1st n dispatched execution by '> n'
@@ -922,9 +921,7 @@ def load_kernel_top(workload, dir):
if file.exists(): if file.exists():
tmp[id] = pd.read_csv(file) tmp[id] = pd.read_csv(file)
else: else:
logging.info( console_warning("Issue loading top kernels. Check pmc_kernel_top.csv")
"Warning: Issue loading top kernels. Check pmc_kernel_top.csv"
)
# NB: Special case for sysinfo. Probably room for improvement in this whole function design # NB: Special case for sysinfo. Probably room for improvement in this whole function design
elif "from_csv_columnwise" in df.columns and id == 101: elif "from_csv_columnwise" in df.columns and id == 101:
tmp[id] = workload.sys_info.transpose() tmp[id] = workload.sys_info.transpose()
@@ -942,9 +939,7 @@ def load_kernel_top(workload, dir):
# so tty could detect them and show them correctly in comparison. # so tty could detect them and show them correctly in comparison.
tmp[id].columns = ["Info"] tmp[id].columns = ["Info"]
else: else:
logging.info( console_warning("Issue loading top kernels. Check pmc_kernel_top.csv")
"Warning: Issue loading top kernels. Check pmc_kernel_top.csv"
)
workload.dfs.update(tmp) workload.dfs.update(tmp)
@@ -988,8 +983,8 @@ def correct_sys_info(mspec, specs_correction: dict):
for k, v in pairs.items(): for k, v in pairs.items():
if not hasattr(mspec, str(k)): if not hasattr(mspec, str(k)):
error( console_error(
f"Invalid specs correction '{k}'. Please use --specs option to peak valid specs" "analyze", f"Invalid specs correction '{k}'. Please use --specs option to peak valid specs"
) )
setattr(mspec, str(k), v) setattr(mspec, str(k), v)
return mspec.get_class_members() return mspec.get_class_members()
@@ -25,7 +25,7 @@
import os import os
from dataclasses import dataclass from dataclasses import dataclass
import logging from utils.utils import console_debug
import csv import csv
################################################ ################################################
@@ -112,8 +112,11 @@ def calc_ceilings(roofline_parameters, dtype, benchmark_data):
if dtype != "FP16" and dtype != "I8": if dtype != "FP16" and dtype != "I8":
peakOps = float(benchmark_data[dtype + "Flops"][roofline_parameters["device_id"]]) peakOps = float(benchmark_data[dtype + "Flops"][roofline_parameters["device_id"]])
for i in range(0, len(cacheHierarchy)): for i in range(0, len(cacheHierarchy)):
# Plot BW line # Plot BW line
logging.debug("[roofline] Current cache level is %s" % cacheHierarchy[i]) console_debug(
"roofline"
"Current cache level is %s" % cacheHierarchy[i]
)
curr_bw = cacheHierarchy[i] + "Bw" curr_bw = cacheHierarchy[i] + "Bw"
peakBw = float(benchmark_data[curr_bw][roofline_parameters["device_id"]]) peakBw = float(benchmark_data[curr_bw][roofline_parameters["device_id"]])
@@ -143,9 +146,12 @@ def calc_ceilings(roofline_parameters, dtype, benchmark_data):
y2_mfma = peakMFMA y2_mfma = peakMFMA
# These are the points to use: # These are the points to use:
logging.debug("[roofline] coordinate points:") console_debug(
logging.debug("x = [{}, {}]".format(x1, x2_mfma)) "roofline",
logging.debug("y = [{}, {}]".format(y1, y2_mfma)) "coordinate points:"
)
console_debug("x = [{}, {}]".format(x1, x2_mfma))
console_debug("y = [{}, {}]".format(y1, y2_mfma))
graphPoints[cacheHierarchy[i].lower()].append([x1, x2_mfma]) graphPoints[cacheHierarchy[i].lower()].append([x1, x2_mfma])
graphPoints[cacheHierarchy[i].lower()].append([y1, y2_mfma]) graphPoints[cacheHierarchy[i].lower()].append([y1, y2_mfma])
@@ -161,7 +167,7 @@ def calc_ceilings(roofline_parameters, dtype, benchmark_data):
if x2 < x0: if x2 < x0:
x0 = x2 x0 = x2
logging.debug("FMA ROOF [{}, {}], [{},{}]".format(x0, XMAX, peakOps, peakOps)) console_debug("FMA ROOF [{}, {}], [{},{}]".format(x0, XMAX, peakOps, peakOps))
graphPoints["valu"].append([x0, XMAX]) graphPoints["valu"].append([x0, XMAX])
graphPoints["valu"].append([peakOps, peakOps]) graphPoints["valu"].append([peakOps, peakOps])
graphPoints["valu"].append(peakOps) graphPoints["valu"].append(peakOps)
@@ -174,9 +180,7 @@ def calc_ceilings(roofline_parameters, dtype, benchmark_data):
if x2_mfma < x0_mfma: if x2_mfma < x0_mfma:
x0_mfma = x2_mfma x0_mfma = x2_mfma
logging.debug( console_debug("MFMA ROOF [{}, {}], [{},{}]".format(x0_mfma, XMAX, peakMFMA, peakMFMA))
"MFMA ROOF [{}, {}], [{},{}]".format(x0_mfma, XMAX, peakMFMA, peakMFMA)
)
graphPoints["mfma"].append([x0_mfma, XMAX]) graphPoints["mfma"].append([x0_mfma, XMAX])
graphPoints["mfma"].append([peakMFMA, peakMFMA]) graphPoints["mfma"].append([peakMFMA, peakMFMA])
graphPoints["mfma"].append(peakMFMA) graphPoints["mfma"].append(peakMFMA)
@@ -253,10 +257,9 @@ def calc_ai(sort_type, ret_df):
+ (df["SQ_INSTS_VALU_MFMA_MOPS_F64"][idx] * 512) + (df["SQ_INSTS_VALU_MFMA_MOPS_F64"][idx] * 512)
) )
except KeyError: except KeyError:
logging.debug( console_debug(
"[roofline] {}: Skipped total_flops at index {}".format( "roofline",
kernelName[:35], idx "{}: Skipped total_flops at index {}".format(kernelName[:35], idx)
)
) )
pass pass
try: try:
@@ -284,9 +287,9 @@ def calc_ai(sort_type, ret_df):
) )
) )
except KeyError: except KeyError:
logging.debug( console_debug(
"{}: Skipped valu_flops at index {}".format(kernelName[:35], idx) "roofline",
) "{}: Skipped valu_flops at index {}".format(kernelName[:35], idx))
pass pass
try: try:
@@ -296,8 +299,9 @@ def calc_ai(sort_type, ret_df):
mfma_flops_f64 += df["SQ_INSTS_VALU_MFMA_MOPS_F64"][idx] * 512 mfma_flops_f64 += df["SQ_INSTS_VALU_MFMA_MOPS_F64"][idx] * 512
mfma_iops_i8 += df["SQ_INSTS_VALU_MFMA_MOPS_I8"][idx] * 512 mfma_iops_i8 += df["SQ_INSTS_VALU_MFMA_MOPS_I8"][idx] * 512
except KeyError: except KeyError:
logging.debug( console_debug(
"[roofline] {}: Skipped mfma ops at index {}".format(kernelName[:35], idx) "roofline",
"{}: Skipped mfma ops at index {}".format(kernelName[:35], idx)
) )
pass pass
@@ -308,18 +312,18 @@ def calc_ai(sort_type, ret_df):
* L2_BANKS * L2_BANKS
) # L2_BANKS = 32 (since assuming mi200) ) # L2_BANKS = 32 (since assuming mi200)
except KeyError: except KeyError:
logging.debug( console_debug(
"[roofline] {}: Skipped lds_data at index {}".format(kernelName[:35], idx) "roofline",
"{}: Skipped lds_data at index {}".format(kernelName[:35], idx)
) )
pass pass
try: try:
L1cache_data += df["TCP_TOTAL_CACHE_ACCESSES_sum"][idx] * 64 L1cache_data += df["TCP_TOTAL_CACHE_ACCESSES_sum"][idx] * 64
except KeyError: except KeyError:
logging.debug( console_debug(
"[roofline] {}: Skipped L1cache_data at index {}".format( "roofline",
kernelName[:35], idx "{}: Skipped L1cache_data at index {}".format(kernelName[:35], idx)
)
) )
pass pass
@@ -331,10 +335,9 @@ def calc_ai(sort_type, ret_df):
+ df["TCP_TCC_READ_REQ_sum"][idx] * 64 + df["TCP_TCC_READ_REQ_sum"][idx] * 64
) )
except KeyError: except KeyError:
logging.debug( console_debug(
"[roofline] {}: Skipped L2cache_data at index {}".format( "roofline",
kernelName[:35], idx "{}: Skipped L2cache_data at index {}".format(kernelName[:35], idx)
)
) )
pass pass
try: try:
@@ -345,8 +348,9 @@ def calc_ai(sort_type, ret_df):
+ ((df["TCC_EA_WRREQ_sum"][idx] - df["TCC_EA_WRREQ_64B_sum"][idx]) * 32) + ((df["TCC_EA_WRREQ_sum"][idx] - df["TCC_EA_WRREQ_64B_sum"][idx]) * 32)
) )
except KeyError: except KeyError:
logging.debug( console_debug(
"[roofline] {}: Skipped hbm_data at index {}".format(kernelName[:35], idx) "roofline",
"{}: Skipped hbm_data at index {}".format(kernelName[:35], idx)
) )
pass pass
@@ -375,7 +379,7 @@ def calc_ai(sort_type, ret_df):
avgDuration / calls, avgDuration / calls,
) )
) )
logging.debug( console_debug(
"Just added {} to AI_Data at index {}. # of calls: {}".format( "Just added {} to AI_Data at index {}. # of calls: {}".format(
kernelName, idx, calls kernelName, idx, calls
) )
+20 -25
View File
@@ -30,7 +30,6 @@ import sys
import socket import socket
import subprocess import subprocess
import importlib import importlib
import logging
import config import config
import pandas as pd import pandas as pd
@@ -38,7 +37,7 @@ from datetime import datetime
from math import ceil from math import ceil
from dataclasses import dataclass, field, fields from dataclasses import dataclass, field, fields
from pathlib import Path as path from pathlib import Path as path
from utils.utils import error, get_hbm_stack_num, get_version from utils.utils import get_hbm_stack_num, get_version, console_error, console_warning, console_log
from utils.tty import get_table_string from utils.tty import get_table_string
VERSION_LOC = [ VERSION_LOC = [
@@ -64,7 +63,7 @@ def detect_arch(_rocminfo):
gpu_arch = str(gpu_arch) gpu_arch = str(gpu_arch)
break break
if not gpu_arch in SUPPORTED_ARCHS.keys(): if not gpu_arch in SUPPORTED_ARCHS.keys():
error("[profiling] Cannot find a supported arch in rocminfo") console_error("Cannot find a supported arch in rocminfo")
else: else:
return (gpu_arch, idx1) return (gpu_arch, idx1)
@@ -84,12 +83,12 @@ def generate_machine_specs(args, sysinfo: dict = None):
try: try:
sysinfo_ver = str(sysinfo["version"]) sysinfo_ver = str(sysinfo["version"])
except KeyError: except KeyError:
error( console_error(
"Detected mismatch in sysinfo versioning. You need to reprofile to update data." "Detected mismatch in sysinfo versioning. You need to reprofile to update data."
) )
version = get_version(config.omniperf_home)["version"] version = get_version(config.omniperf_home)["version"]
if sysinfo_ver != version[: version.find(".")]: if sysinfo_ver != version[: version.find(".")]:
error( console_error(
"Detected mismatch in sysinfo versioning. You need to reprofile to update data." "Detected mismatch in sysinfo versioning. You need to reprofile to update data."
) )
return MachineSpecs(**sysinfo) return MachineSpecs(**sysinfo)
@@ -172,7 +171,7 @@ def generate_machine_specs(args, sysinfo: dict = None):
try: try:
soc_module = importlib.import_module("omniperf_soc.soc_" + specs.gpu_arch) soc_module = importlib.import_module("omniperf_soc.soc_" + specs.gpu_arch)
except ModuleNotFoundError as e: except ModuleNotFoundError as e:
error( console_error(
"Arch %s marked as supported, but couldn't find class implementation %s." "Arch %s marked as supported, but couldn't find class implementation %s."
% (specs.gpu_arch, e) % (specs.gpu_arch, e)
) )
@@ -513,16 +512,15 @@ class MachineSpecs:
): ):
pass pass
else: else:
# TODO: use proper logging function when that's merged console_warning(
logging.warning( f"Incomplete class definition for {self.gpu_arch}. "
f"WARNING: Incomplete class definition for {self.gpu_arch}. "
f"Expecting populated {name} but detected None." f"Expecting populated {name} but detected None."
) )
all_populated = False all_populated = False
data[name] = value data[name] = value
if not all_populated: if not all_populated:
error("Missing specs fields for %s" % self.gpu_arch) console_error("Missing specs fields for %s" % self.gpu_arch)
return pd.DataFrame(data, index=[0]) return pd.DataFrame(data, index=[0])
def __repr__(self): def __repr__(self):
@@ -539,7 +537,7 @@ class MachineSpecs:
if name == "version": if name == "version":
topstr += f"Output version: {value}\n" topstr += f"Output version: {value}\n"
else: else:
error(f"Unknown out of table printing field: {name}") console_error(f"Unknown out of table printing field: {name}")
continue continue
if "name" in field.metadata: if "name" in field.metadata:
name = field.metadata["name"] name = field.metadata["name"]
@@ -573,17 +571,16 @@ def get_rocm_ver():
# check if ROCM_VER is supplied externally # check if ROCM_VER is supplied externally
ROCM_VER_USER = os.getenv("ROCM_VER") ROCM_VER_USER = os.getenv("ROCM_VER")
if ROCM_VER_USER is not None: if ROCM_VER_USER is not None:
logging.info( console_log(
"Overriding missing ROCm version detection with ROCM_VER = %s" "profiling",
% ROCM_VER_USER "Overriding missing ROCm version detection with ROCM_VER = %s" % ROCM_VER_USER
) )
rocm_ver = ROCM_VER_USER rocm_ver = ROCM_VER_USER
else: else:
_rocm_path = os.getenv("ROCM_PATH", "/opt/rocm") _rocm_path = os.getenv("ROCM_PATH", "/opt/rocm")
error( console_warning("Unable to detect a complete local ROCm installation.")
"Unable to detect a complete local ROCm installation.\nThe expected %s/.info/ versioning directory is missing. Please ensure you have valid ROCm installation." console_warning("The expected %s/.info/ versioning directory is missing." % _rocm_path)
% _rocm_path console_error("Ensure you have valid ROCm installation.")
)
return rocm_ver return rocm_ver
@@ -591,18 +588,16 @@ def run(cmd, exit_on_error=False):
try: try:
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except FileNotFoundError as e: except FileNotFoundError as e:
error( console_error(
f"Unable to parse specs. Can't find ROCm asset: {e.filename}\nTry passing a path to an existing workload results in 'analyze' mode." f"Unable to parse specs. Can't find ROCm asset: {e.filename}\nTry passing a path to an existing workload results in 'analyze' mode."
) )
if exit_on_error: if exit_on_error:
if cmd[0] == "rocm-smi": if cmd[0] == "rocm-smi":
if p.returncode != 2 and p.returncode != 0: if p.returncode != 2 and p.returncode != 0:
logging.error("ERROR: No GPU detected. Unable to load rocm-smi") console_error("No GPU detected. Unable to load rocm-smi")
sys.exit(1)
elif p.returncode != 0: elif p.returncode != 0:
logging.error("ERROR: command [%s] failed with non-zero exit code" % cmd) console_error("Command [%s] failed with non-zero exit code" % cmd)
sys.exit(1)
return p.stdout.decode("utf-8") return p.stdout.decode("utf-8")
@@ -638,7 +633,7 @@ def total_xcds(archname, compute_partition):
mi300a_archs = ["mi300a_a0", "mi300a_a1"] mi300a_archs = ["mi300a_a0", "mi300a_a1"]
mi300x_archs = ["mi300x_a0", "mi300x_a1"] mi300x_archs = ["mi300x_a0", "mi300x_a1"]
if archname.lower() in mi300a_archs + mi300x_archs and compute_partition == "NA": if archname.lower() in mi300a_archs + mi300x_archs and compute_partition == "NA":
error("Invalid compute partition found for {}".format(archname)) console_error("Invalid compute partition found for {}".format(archname))
if archname.lower() not in mi300a_archs + mi300x_archs: if archname.lower() not in mi300a_archs + mi300x_archs:
return 1 return 1
# from the whitepaper # from the whitepaper
@@ -660,7 +655,7 @@ def total_xcds(archname, compute_partition):
if compute_partition.lower() == "cpx": if compute_partition.lower() == "cpx":
if archname.lower() in mi300x_archs: if archname.lower() in mi300x_archs:
return 2 return 2
error( console_error(
"Unknown compute partition / arch found for {} / {}".format( "Unknown compute partition / arch found for {} / {}".format(
compute_partition, archname compute_partition, archname
) )
@@ -25,10 +25,10 @@
import pandas as pd import pandas as pd
from pathlib import Path from pathlib import Path
from tabulate import tabulate from tabulate import tabulate
import sys
import copy import copy
from utils import parser from utils import parser
from utils.utils import console_warning, console_log
hidden_columns = ["Tips", "coll_level"] hidden_columns = ["Tips", "coll_level"]
hidden_sections = [1900, 2000] hidden_sections = [1900, 2000]
@@ -135,7 +135,7 @@ def show_all(args, runs, archConfigs, output):
0, 1 0, 1
) )
if args.verbose >= 2: if args.verbose >= 2:
print("---------", header, t_df) console_log("---------", header, t_df)
t_df_pretty = ( t_df_pretty = (
t_df.astype(float) t_df.astype(float)
@@ -168,13 +168,8 @@ def show_all(args, runs, archConfigs, output):
violation_idx = t_df_pretty.index[ violation_idx = t_df_pretty.index[
t_df_pretty.abs() > args.report_diff t_df_pretty.abs() > args.report_diff
] ]
print( console_warning("Dataframe diff exceeds %s threshold requirement\nSee metric %s" % (str(args.report_diff) + "%", violation_idx.to_numpy()))
"DEBUG ERROR: Dataframe diff exceeds {} threshold requirement\nSee metric {}".format( console_warning(df)
str(args.report_diff) + "%",
violation_idx.to_numpy(),
)
)
print(df)
else: else:
cur_df_copy = copy.deepcopy(cur_df) cur_df_copy = copy.deepcopy(cur_df)