Merge pull request #55 from AMDResearch/dev

Merge features for v1.0.5
This commit is contained in:
Cole Ramos
2022-12-12 16:43:52 -06:00
zatwierdzone przez GitHub
300 zmienionych plików z 13639 dodań i 22734 usunięć
+8 -6
Wyświetl plik
@@ -216,11 +216,11 @@ install(PROGRAMS src/omniperf TYPE BIN)
install(FILES src/parser.py TYPE BIN) install(FILES src/parser.py TYPE BIN)
install(FILES src/common.py TYPE BIN) install(FILES src/common.py TYPE BIN)
install(FILES VERSION VERSION.sha DESTINATION ${CMAKE_INSTALL_PREFIX}) install(FILES VERSION VERSION.sha DESTINATION ${CMAKE_INSTALL_PREFIX})
# src/omniperf_cli # src/omniperf_analyze
install( install(
DIRECTORY src/omniperf_cli DIRECTORY src/omniperf_analyze
TYPE BIN TYPE BIN
PATTERN src/omniperf_cli/tests EXCLUDE PATTERN src/omniperf_analyze/tests EXCLUDE
PATTERN "__pycache__" EXCLUDE) PATTERN "__pycache__" EXCLUDE)
# src/utils # src/utils
install( install(
@@ -228,9 +228,11 @@ install(
TYPE BIN TYPE BIN
PATTERN "rooflines*" EXCLUDE) PATTERN "rooflines*" EXCLUDE)
# src/utils/rooflines # src/utils/rooflines
install(PROGRAMS src/utils/rooflines/roofline-rhel8-mi200-rocm5 install(
src/utils/rooflines/roofline-sle15sp3-mi200-rocm5 PROGRAMS src/utils/rooflines/roofline-rhel8-mi200-rocm5
DESTINATION ${CMAKE_INSTALL_BINDIR}/utils/rooflines) src/utils/rooflines/roofline-sle15sp3-mi200-rocm5
src/utils/rooflines/roofline-ubuntu20_04-mi200-rocm5
DESTINATION ${CMAKE_INSTALL_BINDIR}/utils/rooflines)
# src/perfmon_pub # src/perfmon_pub
install( install(
DIRECTORY src/perfmon_pub DIRECTORY src/perfmon_pub
File diff suppressed because one or more lines are too long
+7 -7
Wyświetl plik
@@ -13,19 +13,19 @@
"author": "Audacious Software Group", "author": "Audacious Software Group",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@grafana/data": "latest",
"@grafana/toolkit": "latest", "@grafana/toolkit": "latest",
"@grafana/ui": "latest", "emotion": "10.0.27",
"emotion": "10.0.27" "react-monaco-editor": "^0.44.0",
"tslib": "^2.3.1"
}, },
"engines": { "engines": {
"node": ">=14" "node": ">=14"
}, },
"dependencies": { "dependencies": {
"@grafana/runtime": "^8.1.1", "@grafana/runtime": "9.1.2",
"@svgdotjs/svg.js": "^3.1.1", "@grafana/data": "9.1.2",
"react-monaco-editor": "^0.44.0", "@grafana/ui": "9.1.2",
"tslib": "^2.3.1" "@svgdotjs/svg.js": "^3.1.1"
}, },
"_comments": "Dependencies are not included as part of Omniperf. It's the user's responsibility to accept any licensing implications before building the project." "_comments": "Dependencies are not included as part of Omniperf. It's the user's responsibility to accept any licensing implications before building the project."
} }
+1 -1
Wyświetl plik
@@ -31,5 +31,5 @@ pythonpath = [
".", ".",
"src", "src",
"src/utils", "src/utils",
"src/omniperf_cli/utils" "src/omniperf_analyze/utils"
] ]
+2
Wyświetl plik
@@ -52,6 +52,8 @@ extensions = [
"myst_parser", "myst_parser",
] ]
myst_heading_anchors = 2
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"] templates_path = ["_templates"]
+3 -1
Wyświetl plik
@@ -69,7 +69,9 @@ Modes change the fundamental behavior of the Omniperf command line tool. Dependi
- **Database**: Our detailed Grafana GUI is built on a MongoDB database. `--import` profiling results to the DB to interact with the workload in Grafana or `--remove` the workload from the DB. - **Database**: Our detailed Grafana GUI is built on a MongoDB database. `--import` profiling results to the DB to interact with the workload in Grafana or `--remove` the workload from the DB.
Connection options will need to be specified. See the [*Omniperf Performance Analysis*](performance_analysis.md#omniperf-grafana-gui-import) section for more details on this. Connection options will need to be specified. See the [*Grafana
Analysis*](grafana_analyzer.md#grafana-gui-import) import section
for more details on this.
```shell ```shell
$ omniperf database --help $ omniperf database --help
+5
Wyświetl plik
@@ -68,6 +68,11 @@ The uniform color coding is applied to most visualizations (bars, table, diagram
## Grafana GUI Import ## Grafana GUI Import
The omniperf database `--import` option imports the raw profiling data to Grafana's backend MongoDB database. This step is only required for Grafana GUI based performance analysis. The omniperf database `--import` option imports the raw profiling data to Grafana's backend MongoDB database. This step is only required for Grafana GUI based performance analysis.
Default username and password for MongoDB (to be used in database mode) are as follows:
- Username: **temp**
- Password: **temp123**
Each workload is imported to a separate database with the following naming convention: Each workload is imported to a separate database with the following naming convention:
omniperf_<team>_<database>_<soc> omniperf_<team>_<database>_<soc>
+1 -1
Wyświetl plik
@@ -180,7 +180,7 @@ $ sudo docker-compose up -d
> Note that TCP ports for Grafana (4000) and MongoDB (27017) in the docker container are mapped to 14000 and 27018, respectively, on the host side. > Note that TCP ports for Grafana (4000) and MongoDB (27017) in the docker container are mapped to 14000 and 27018, respectively, on the host side.
### Setup Grafana Instance ### Setup Grafana Instance
Once you've launced your docker container you should be able to reach Grafana at **http://\<host-ip>:1400**. The default login credentials for the first-time Grafana setup are: Once you've launced your docker container you should be able to reach Grafana at **http://\<host-ip>:14000**. The default login credentials for the first-time Grafana setup are:
- Username: **admin** - Username: **admin**
- Password: **admin** - Password: **admin**
+1 -1
Wyświetl plik
@@ -41,7 +41,7 @@ Analyze
Dash is running on http://0.0.0.0:8050/ Dash is running on http://0.0.0.0:8050/
* Serving Flask app 'omniperf_cli.omniperf_cli' (lazy loading) * Serving Flask app 'omniperf_analyze.omniperf_analyze' (lazy loading)
* Environment: production * Environment: production
WARNING: This is a development server. Do not use it in a production deployment. WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead. Use a production WSGI server instead.
+65 -32
Wyświetl plik
@@ -30,6 +30,7 @@ import glob
import pandas as pd import pandas as pd
from datetime import datetime from datetime import datetime
from pathlib import Path as path from pathlib import Path as path
import warnings
from parser import parse from parser import parse
from utils import specs from utils import specs
@@ -37,7 +38,7 @@ from utils.perfagg import perfmon_filter, pmc_filter
from utils import remove_workload from utils import remove_workload
from utils import csv_converter # Import workload from utils import csv_converter # Import workload
from utils import plot_roofline # standalone roofline from utils import plot_roofline # standalone roofline
from omniperf_cli.omniperf_cli import omniperf_cli # CLI analysis from omniperf_analyze.omniperf_analyze import analyze # CLI analysis
from common import ( from common import (
OMNIPERF_HOME, OMNIPERF_HOME,
@@ -51,6 +52,12 @@ from common import getVersion
################################################ ################################################
# Helper Functions # Helper Functions
################################################ ################################################
def run_subprocess(cmd):
subprocess.run(
cmd,
check=True
)
def resolve_rocprof(): def resolve_rocprof():
# ROCPROF INFO # ROCPROF INFO
global rocprof_cmd global rocprof_cmd
@@ -71,6 +78,7 @@ def resolve_rocprof():
print("ROC Profiler: ", rocprof_path.stdout.decode("utf-8")) print("ROC Profiler: ", rocprof_path.stdout.decode("utf-8"))
def get_soc(): def get_soc():
mspec = specs.get_machine_specs(0) mspec = specs.get_machine_specs(0)
@@ -108,20 +116,24 @@ def isWorkloadEmpty(my_parser, path):
def replace_timestamps(workload_dir): def replace_timestamps(workload_dir):
df_stamps = pd.read_csv(workload_dir + "/timestamps.csv") df_stamps = pd.read_csv(workload_dir + "/timestamps.csv")
df_pmc_perf = pd.read_csv(workload_dir + "/pmc_perf.csv") if "BeginNs" in df_stamps.columns and "EndNs" in df_stamps.columns:
df_pmc_perf = pd.read_csv(workload_dir + "/pmc_perf.csv")
df_pmc_perf["BeginNs"] = df_stamps["BeginNs"] df_pmc_perf["BeginNs"] = df_stamps["BeginNs"]
df_pmc_perf["EndNs"] = df_stamps["EndNs"] df_pmc_perf["EndNs"] = df_stamps["EndNs"]
df_pmc_perf.to_csv(workload_dir + "/pmc_perf.csv", index=False) df_pmc_perf.to_csv(workload_dir + "/pmc_perf.csv", index=False)
else:
warnings.warn("WARNING: Incomplete profiling data detected. Unable to update timestamps.")
def gen_sysinfo(workload_name, workload_dir, ip_blocks, skip_roof): def gen_sysinfo(workload_name, workload_dir, ip_blocks, app_cmd, skip_roof):
# Record system information # Record system information
mspec = specs.get_machine_specs(0) mspec = specs.get_machine_specs(0)
sysinfo = open(workload_dir + "/" + "sysinfo.csv", "w") sysinfo = open(workload_dir + "/" + "sysinfo.csv", "w")
# write header # write header
header = "workload_name," header = "workload_name,"
header += "command,"
header += "host_name,host_cpu,host_distro,host_kernel,host_rocmver,date," header += "host_name,host_cpu,host_distro,host_kernel,host_rocmver,date,"
header += "gpu_soc,numSE,numCU,numSIMD,waveSize,maxWavesPerCU,maxWorkgroupSize," header += "gpu_soc,numSE,numCU,numSIMD,waveSize,maxWavesPerCU,maxWorkgroupSize,"
header += "L1,L2,sclk,mclk,cur_sclk,cur_mclk,L2Banks,name,numSQC,hbmBW," header += "L1,L2,sclk,mclk,cur_sclk,cur_mclk,L2Banks,name,numSQC,hbmBW,"
@@ -136,6 +148,7 @@ def gen_sysinfo(workload_name, workload_dir, ip_blocks, skip_roof):
timestamp = now.strftime("%c") + " (" + local_tzname + ")" timestamp = now.strftime("%c") + " (" + local_tzname + ")"
# host info # host info
param = [workload_name] param = [workload_name]
param += [app_cmd]
param += [ param += [
mspec.hostname, mspec.hostname,
mspec.cpu, mspec.cpu,
@@ -195,10 +208,12 @@ def mongo_import(args, profileAndImport):
csv_converter.convert_folder(connectionInfo, Extractionlvl) csv_converter.convert_folder(connectionInfo, Extractionlvl)
print("-- Complete! --") print("-- Complete! --")
################################################ ################################################
# Roofline Helpers # Roofline Helpers
################################################ ################################################
def detect_roofline(): def detect_roofline():
mspec = specs.get_machine_specs(0) mspec = specs.get_machine_specs(0)
rocm_ver = mspec.rocmversion[:1] rocm_ver = mspec.rocmversion[:1]
@@ -212,7 +227,7 @@ def detect_roofline():
rooflineBinary = os.environ["ROOFLINE_BIN"] rooflineBinary = os.environ["ROOFLINE_BIN"]
if os.path.exists(rooflineBinary): if os.path.exists(rooflineBinary):
print("Detected user-supplied binary") print("Detected user-supplied binary")
return {"rocm_ver":"override", "distro":"override", "path":rooflineBinary} return {"rocm_ver": "override", "distro": "override", "path": rooflineBinary}
else: else:
print("ROOFLINE ERROR: user-supplied path to binary not accessible") print("ROOFLINE ERROR: user-supplied path to binary not accessible")
print("--> ROOFLINE_BIN = %s\n" % target_binary) print("--> ROOFLINE_BIN = %s\n" % target_binary)
@@ -230,26 +245,34 @@ def detect_roofline():
print("ROOFLINE ERROR: Cannot find a valid binary for your operating system") print("ROOFLINE ERROR: Cannot find a valid binary for your operating system")
sys.exit(1) sys.exit(1)
target_binary = { "rocm_ver":rocm_ver, "distro":distro } target_binary = {"rocm_ver": rocm_ver, "distro": distro}
return target_binary return target_binary
def mibench(args): def mibench(args):
print("No roofline data found. Generating...") print("No roofline data found. Generating...")
target_binary = detect_roofline() target_binary = detect_roofline()
if target_binary["rocm_ver"] == "override": if target_binary["rocm_ver"] == "override":
path_to_binary = target_binary["path"] path_to_binary = target_binary["path"]
else: else:
path_to_binary = str(OMNIPERF_HOME) + "/utils/rooflines/roofline" + "-" + DISTRO_MAP[target_binary["distro"]] + "-" + args.target.lower() + "-rocm" + target_binary["rocm_ver"] path_to_binary = (
str(OMNIPERF_HOME)
+ "/utils/rooflines/roofline"
+ "-"
+ DISTRO_MAP[target_binary["distro"]]
+ "-"
+ args.target.lower()
+ "-rocm"
+ target_binary["rocm_ver"]
)
# Distro is valid but cant find rocm ver # Distro is valid but cant find rocm ver
if not os.path.exists(path_to_binary): if not os.path.exists(path_to_binary):
print( print("ROOFLINE ERROR: Unable to locate expected binary (%s)." % path_to_binary)
"ROOFLINE ERROR: ROCm version not supported."
)
sys.exit(1) sys.exit(1)
subprocess.run( run_subprocess(
[ [
path_to_binary, path_to_binary,
"-o", "-o",
@@ -276,6 +299,7 @@ def characterize_app(path, cmd, verbose):
print(fname) print(fname)
run_prof(fname, workload_dir, perfmon_dir, app_cmd, verbose) run_prof(fname, workload_dir, perfmon_dir, app_cmd, verbose)
################################################ ################################################
# Profiling Helpers # Profiling Helpers
################################################ ################################################
@@ -290,13 +314,11 @@ def run_prof(fname, workload_dir, perfmon_dir, cmd, verbose):
print("pmc file:", os.path.basename(fname)) print("pmc file:", os.path.basename(fname))
# profile the app # profile the app
subprocess.run( run_subprocess(
[ [
rocprof_cmd, rocprof_cmd,
"-i", "-i",
fname, fname,
"-m",
perfmon_dir + "/" + "metrics.xml",
"--timestamp", "--timestamp",
"on", "on",
"-o", "-o",
@@ -306,7 +328,7 @@ def run_prof(fname, workload_dir, perfmon_dir, cmd, verbose):
) )
def omniperf_profile(args,VER): def omniperf_profile(args, VER):
# Verify valid target # Verify valid target
if args.target not in SOC_LIST: if args.target not in SOC_LIST:
parse.print_help(sys.stderr) parse.print_help(sys.stderr)
@@ -335,7 +357,7 @@ def omniperf_profile(args,VER):
for fname in glob.glob(workload_dir + "/perfmon/*.txt"): for fname in glob.glob(workload_dir + "/perfmon/*.txt"):
# Kernel filtering (in-place replacement) # Kernel filtering (in-place replacement)
if not args.kernel == None: if not args.kernel == None:
subprocess.run( run_subprocess(
[ [
"sed", "sed",
"-i", "-i",
@@ -347,7 +369,7 @@ def omniperf_profile(args,VER):
# Dispatch filtering (inplace replacement) # Dispatch filtering (inplace replacement)
if not args.dispatch == None: if not args.dispatch == None:
subprocess.run( run_subprocess(
[ [
"sed", "sed",
"-i", "-i",
@@ -359,7 +381,7 @@ def omniperf_profile(args,VER):
run_prof(fname, workload_dir, perfmon_dir, args.remaining, args.verbose) run_prof(fname, workload_dir, perfmon_dir, args.remaining, args.verbose)
# run again with timestamps # run again with timestamps
subprocess.run( run_subprocess(
[ [
rocprof_cmd, rocprof_cmd,
# "-i", fname, # "-i", fname,
@@ -376,7 +398,7 @@ def omniperf_profile(args,VER):
replace_timestamps(workload_dir) replace_timestamps(workload_dir)
# Generate sysinfo # Generate sysinfo
gen_sysinfo(args.name, workload_dir, args.ipblocks, args.no_roof) gen_sysinfo(args.name, workload_dir, args.ipblocks, args.remaining, args.no_roof)
# Add tracing & roofline metrics (mi200 only) # Add tracing & roofline metrics (mi200 only)
if args.target.lower() == "mi200": if args.target.lower() == "mi200":
@@ -386,15 +408,25 @@ def omniperf_profile(args,VER):
if target_binary["rocm_ver"] == "override": if target_binary["rocm_ver"] == "override":
path_to_binary = target_binary["path"] path_to_binary = target_binary["path"]
else: else:
path_to_binary = str(OMNIPERF_HOME) + "/utils/rooflines/roofline" + "-" + DISTRO_MAP[target_binary["distro"]] + "-" + args.target.lower() + "-rocm" + target_binary["rocm_ver"] path_to_binary = (
# Distro is valid but cant find rocm ver str(OMNIPERF_HOME)
+ "/utils/rooflines/roofline"
+ "-"
+ DISTRO_MAP[target_binary["distro"]]
+ "-"
+ args.target.lower()
+ "-rocm"
+ target_binary["rocm_ver"]
)
# Distro is valid but cant find valid binary
if not os.path.exists(path_to_binary): if not os.path.exists(path_to_binary):
print( print(
"ROOFLINE ERROR: ROCm version not supported." "ROOFLINE ERROR: Unable to locate expected binary (%s))."
% path_to_binary
) )
sys.exit(1) sys.exit(1)
subprocess.run( run_subprocess(
[ [
path_to_binary, path_to_binary,
"-o", "-o",
@@ -404,6 +436,7 @@ def omniperf_profile(args,VER):
] ]
) )
################################################ ################################################
# MAIN # MAIN
################################################ ################################################
@@ -422,7 +455,7 @@ def main():
args = my_parser.parse_args() args = my_parser.parse_args()
vData = getVersion() vData = getVersion()
VER = vData['version'] VER = vData["version"]
if args.mode == None: if args.mode == None:
throw_parse_error( throw_parse_error(
@@ -498,7 +531,7 @@ def main():
sysinfo_exists = os.path.isfile(sysinfo_path) sysinfo_exists = os.path.isfile(sysinfo_path)
if not sysinfo_exists: if not sysinfo_exists:
print("sysinfo not found") print("sysinfo not found")
gen_sysinfo(args.name, args.path, [], False) gen_sysinfo(args.name, args.path, [], args.remaining, False)
# does app data exist? # does app data exist?
print("Checking for pmc_perf.csv in ", args.path) print("Checking for pmc_perf.csv in ", args.path)
@@ -512,7 +545,7 @@ def main():
if not args.remaining: if not args.remaining:
throw_parse_error( throw_parse_error(
my_parser, my_parser,
"Cannot find existing application data.\nAttempting to generate application data from -c.\n--cmd option is required to generate application data.", "Cannot find existing application data.\nAttempting to generate application data from -- <app_cmd>.\n-- <app_cmd> option is required to generate application data.",
) )
else: else:
characterize_app(args.path, args.remaining, args.verbose) characterize_app(args.path, args.remaining, args.verbose)
@@ -522,7 +555,7 @@ def main():
# Profile only # Profile only
else: else:
print("\n-------------\nProfile only\n-------------\n") print("\n-------------\nProfile only\n-------------\n")
omniperf_profile(args,VER) omniperf_profile(args, VER)
############## ##############
# DATABASE MODE # DATABASE MODE
@@ -583,7 +616,7 @@ def main():
############## ##############
if args.mode == "analyze": if args.mode == "analyze":
if args.list_metrics: if args.list_metrics:
omniperf_cli(args) analyze(args)
else: else:
if args.path: if args.path:
if ".." in str(args.path): if ".." in str(args.path):
@@ -607,7 +640,7 @@ def main():
my_parser, dir[0] my_parser, dir[0]
) # Verify workload is valid before analyzing ) # Verify workload is valid before analyzing
omniperf_cli(args) analyze(args)
else: else:
throw_parse_error( throw_parse_error(
my_parser, my_parser,
@@ -1,6 +1,6 @@
# Description # Description
omniperf_cli.py is a post-processing profiling tool with the raw data collected from omniperf. omniperf_analyze.py is a post-processing profiling tool with the raw data collected from omniperf.
## Features ## Features

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 197 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 197 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 3.5 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 3.5 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 187 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 187 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 282 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 282 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 182 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 182 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 116 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 116 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 118 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 118 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 116 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 116 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 118 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 118 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 120 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 120 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 114 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 114 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 120 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 120 KiB

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 117 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 117 KiB

Some files were not shown because too many files have changed in this diff Show More