Files
rocm-systems/plugin/att/trace_view.py
T

354 wiersze
13 KiB
Python
Czysty Zwykły widok Historia

2023-02-07 13:06:02 +05:30
#!/usr/bin/env python3
import sys
if sys.version_info[0] < 3:
raise Exception("Must be using Python 3")
import os
import sys
import time
import socket
from pathlib import Path
from collections import defaultdict
import http.server
import socketserver
import socket
import asyncio
import websockets
from multiprocessing import Process, Manager
import numpy as np
from http import HTTPStatus
2023-04-06 16:55:30 -03:00
from io import BytesIO
2023-06-21 19:49:00 -03:00
from drawing import Readable, GeneratePIC
from copy import deepcopy
JSON_GLOBAL_DICTIONARY = {}
def get_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(0)
try:
hostname = socket.gethostname()
IPAddr = socket.gethostbyname(hostname)
s.connect(({IPAddr}, 1))
except Exception:
IPAddr = '127.0.0.1'
finally:
return IPAddr
IPAddr = get_ip()
PORT, WebSocketPort = 8000, 18000
SP = '\u00A0'
2023-02-07 13:06:02 +05:30
2023-05-02 05:17:47 -03:00
2023-06-21 19:49:00 -03:00
def get_top_n(code):
2023-02-07 13:06:02 +05:30
TOP_N = 10
2023-06-21 19:49:00 -03:00
top_n = sorted(deepcopy(code), key=lambda x: x[-1], reverse=True)[:TOP_N]
return [(line_num, hitc, 0, run_time) for _, _, _, _, line_num, _, hitc, run_time in top_n]
2023-02-07 13:06:02 +05:30
def wave_info(df, id):
dic = {
'Issue': df['issued_ins'][id],
'Valu': df['valu_ins'][id], 'Valu_stall': df['valu_stalls'][id],
'Salu': df['salu_ins'][id], 'Salu_stall': df['salu_stalls'][id],
'Vmem': df['vmem_ins'][id], 'Vmem_stall': df['vmem_stalls'][id],
'Smem': df['smem_ins'][id], 'Smem_stall': df['smem_stalls'][id],
'Flat': df['flat_ins'][id], 'Flat_stall': df['flat_stalls'][id],
'Lds': df['lds_ins'][id], 'Lds_stall': df['lds_stalls'][id],
'Br': df['br_ins'][id], 'Br_stall': df['br_stalls'][id],
}
dic['Issue_stall'] = int(np.sum([dic[key] for key in dic.keys() if '_STALL' in key]))
return dic
2023-02-07 13:06:02 +05:30
2023-06-21 19:49:00 -03:00
def extract_data(df, se_number):
2023-02-07 13:06:02 +05:30
if len(df['id']) == 0 or len(df['instructions']) == 0 or len(df['timeline']) == 0:
return None
wave_filenames = []
2023-02-07 13:06:02 +05:30
flight_count = []
2023-06-21 19:49:00 -03:00
wave_slot_count = [{df['wave_slot'][wave_id]: 0 for wave_id in df['id']} for k in range(4)]
2023-03-15 17:17:57 -03:00
print('Number of waves:', len(df['id']))
allwaves_maxline = 0
2023-02-07 13:06:02 +05:30
for wave_id in df['id']:
2023-06-21 19:49:00 -03:00
stitched, loopCount, mem_unroll, count, maxline, num_insts = df['instructions'][wave_id]
timeline = df['timeline'][wave_id]
2023-02-07 13:06:02 +05:30
2023-06-21 19:49:00 -03:00
if len(stitched) == 0 or len(timeline) == 0 or len(stitched) != num_insts:
2023-03-15 17:17:57 -03:00
continue
allwaves_maxline = max(allwaves_maxline, maxline)
2023-02-07 13:06:02 +05:30
flight_count.append(count)
2023-06-21 19:49:00 -03:00
wave_entry = {
2023-02-07 13:06:02 +05:30
"id": int(df['id'][wave_id]),
"simd": int(df['simd'][wave_id]),
"slot": int(df['wave_slot'][wave_id]),
"begin": int(df['begin_time'][wave_id]),
"end": int(df['end_time'][wave_id]),
"info": wave_info(df, wave_id),
"instructions": stitched,
"timeline": timeline,
"waitcnt": mem_unroll
}
data_obj = {
"name": 'SE'.format(se_number),
"duration": sum(dur for (_, dur) in timeline),
"wave": wave_entry,
"loop_count": loopCount,
2023-06-21 19:49:00 -03:00
"top_n": [],
"num_stitched": len(stitched),
"num_insts": num_insts,
2023-02-07 13:06:02 +05:30
"websocket_port": WebSocketPort,
"generation_time": time.ctime()
}
2023-06-21 19:49:00 -03:00
simd_id = df['simd'][wave_id]
slot_id = df['wave_slot'][wave_id]
slot_count = wave_slot_count[simd_id][slot_id]
wave_slot_count[simd_id][slot_id] += 1
OUT = 'se'+str(se_number)+'_sm'+str(simd_id)+'_sl'+str(slot_id)+'_wv'+str(slot_count)+'.json'
JSON_GLOBAL_DICTIONARY[OUT] = Readable(data_obj)
2023-06-21 19:49:00 -03:00
wave_filenames.append((OUT, df['begin_time'][wave_id], df['end_time'][wave_id]))
data_obj = {
"name": 'SE'.format(se_number),
"websocket_port": WebSocketPort,
"generation_time": time.ctime()
}
2023-06-21 19:49:00 -03:00
se_filename = None
if len(wave_filenames) > 0:
2023-06-21 19:49:00 -03:00
se_filename = 'se'+str(se_number)+'_info.json'
JSON_GLOBAL_DICTIONARY[se_filename] = Readable(data_obj)
2023-02-07 13:06:02 +05:30
2023-06-21 19:49:00 -03:00
return flight_count, wave_filenames, se_filename, allwaves_maxline
2023-02-07 13:06:02 +05:30
class NoCacheHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_my_headers()
http.server.SimpleHTTPRequestHandler.end_headers(self)
def send_my_headers(self):
self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
self.send_header("Pragma", "no-cache")
self.send_header("Expires", "0")
def do_GET(self):
2023-06-21 19:49:00 -03:00
if '.png?' in self.path and self.path.split('/')[-1] not in JSON_GLOBAL_DICTIONARY.keys():
selections = [int(s)!=0 for s in self.path.split('.png?')[-1]]
counters_json, imagebytes = GeneratePIC(self.drawinfo, selections[1:], selections[0])
JSON_GLOBAL_DICTIONARY['graph_options.json'] = counters_json
JSON_GLOBAL_DICTIONARY[self.path.split('/')[-1]] = imagebytes[self.path.split('/')[-1].split('?')[0]]
if '.json' in self.path or '.png' in self.path:
try:
response_file = JSON_GLOBAL_DICTIONARY[self.path.split('/')[-1]]
except:
print('Invalid json request:', self.path)
2023-06-21 19:49:00 -03:00
print(JSON_GLOBAL_DICTIONARY.keys())
self.send_error(HTTPStatus.NOT_FOUND, "File not found")
return
self.send_response(HTTPStatus.OK)
2023-04-06 16:55:30 -03:00
self.send_header("Content-Length", str(len(response_file)))
if '.b' in self.path:
self.send_header("Content-type", 'application/octet-stream')
response_file = BytesIO(response_file)
elif 'timeline.png' in self.path:
self.send_header("Content-type", 'image/png')
else:
self.send_header("Content-type", 'application/json')
self.send_header("Last-Modified", self.date_time_string(time.time()))
self.end_headers()
self.copyfile(response_file, self.wfile)
elif self.path in ['/', '/styles.css', '/index.html', '/logo.svg']:
http.server.SimpleHTTPRequestHandler.do_GET(self)
else:
print('Invalid request:', self.path)
self.send_error(HTTPStatus.NOT_FOUND, "File not found")
2023-02-07 13:06:02 +05:30
class RocTCPServer(socketserver.TCPServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
2023-06-21 19:49:00 -03:00
def run_server(drawinfo):
2023-02-07 13:06:02 +05:30
Handler = NoCacheHTTPRequestHandler
2023-06-21 19:49:00 -03:00
Handler.drawinfo = drawinfo
os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)),'ui/'))
#os.chdir('ui/')
2023-02-07 13:06:02 +05:30
try:
with RocTCPServer((IPAddr, PORT), Handler) as httpd:
httpd.serve_forever()
except KeyboardInterrupt:
pass
def fix_space(line):
line = line.replace(' ', SP)
line = line.replace('\t', SP*4)
return line
def WebSocketserver(websocket, path):
data = websocket.recv()
cpp, ln, _ = data.split(':')
ln = int(ln)
HL, EMP = 'highlight', ''
content = None
print("loading...")
try:
f = open(cpp, 'r', errors='replace')
content = ''.join('<li class=\"line_'+str(i)+
str(HL if i==ln else EMP)+'">'+str(i).ljust(5)+fix_space(l)+'</li>'
for i, l in enumerate(f.readlines(), 1))
except FileNotFoundError:
content = cpp + ' not found!'
websocket.send(content)
def run_websocket():
start_server = websockets.serve(WebSocketserver, IPAddr, WebSocketPort)
try:
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
except KeyboardInterrupt:
pass
def assign_ports(ports):
ps = [int(port) for port in ports.split(',')]
if ps[0] <= 5000 or ps[1] <= 5000:
print('Need to have port values > 5000')
sys.exit(1)
elif ps[0] == ps[1]:
print('Can not use the same port for both web server and websocket server: '+ps[0])
sys.exit(1)
global IPAddr, PORT, WebSocketPort
PORT, WebSocketPort = ps[0], ps[1]
2023-06-21 19:49:00 -03:00
def call_picture_callback(return_dict, drawinfo):
response, imagebytes = GeneratePIC(drawinfo)
return_dict['graph_options.json'] = response
for k, v in imagebytes.items():
return_dict[k] = v
for n, m in enumerate(drawinfo['TIMELINES']):
2023-04-06 16:55:30 -03:00
return_dict['wstates'+str(n)+'.json'] = Readable({"data": [int(n) for n in list(np.asarray(m))]})
2023-06-21 19:49:00 -03:00
for n, e in enumerate(drawinfo['EVENTS']):
2023-04-06 16:55:30 -03:00
return_dict['se'+str(n)+'_perfcounter.json'] = Readable({"data": [v.toTuple() for v in e]})
2023-05-02 05:17:47 -03:00
2023-06-21 19:49:00 -03:00
def view_trace(args, code, dbnames, att_filenames, bReturnLoc, OCCUPANCY, bDumpOnly, se_time_begin, gfxv, drawinfo, MPI_COMM, mpi_root):
global JSON_GLOBAL_DICTIONARY
pic_thread = None
if mpi_root:
manager = Manager()
return_dict = manager.dict()
JSON_GLOBAL_DICTIONARY['occupancy.json'] = Readable({str(k): OCCUPANCY[k] for k in range(len(OCCUPANCY))})
pic_thread = Process(target=call_picture_callback, args=(return_dict, drawinfo))
pic_thread.start()
2023-02-07 13:06:02 +05:30
att_filenames = [Path(f).name for f in att_filenames]
se_numbers = [int(a.split('_se')[1].split('.att')[0]) for a in att_filenames]
flight_count = []
simd_wave_filenames = {}
se_filenames = []
2023-02-07 13:06:02 +05:30
2023-06-21 19:49:00 -03:00
allse_maxline = 0
2023-02-07 13:06:02 +05:30
for se_number, dbname in zip(se_numbers, dbnames):
if len(dbname['id']) == 0:
continue
2023-06-21 19:49:00 -03:00
count, wv_filenames, se_filename, maxline = extract_data(dbname, se_number)
if se_filename is None:
continue
allse_maxline = max(allse_maxline, maxline)
se_filenames.append(se_filename)
2023-02-07 13:06:02 +05:30
if count is not None:
flight_count.append(count)
simd_wave_filenames[se_number] = wv_filenames
2023-06-21 19:49:00 -03:00
if mpi_root:
JSON_GLOBAL_DICTIONARY['code.json'] = Readable({"code": code[:allse_maxline+16], "top_n": get_top_n(code[:allse_maxline+16])})
2023-02-07 13:06:02 +05:30
if bReturnLoc:
return flight_count
for key in simd_wave_filenames.keys():
wv_array = [[
2023-06-21 19:49:00 -03:00
int(s[0].split('_sm')[1].split('_sl')[0]),
int(s[0].split('_sl')[1].split('_wv')[0]),
int(s[0].split('_wv')[1].split('.')[0]),
2023-02-07 13:06:02 +05:30
s
] for s in simd_wave_filenames[key]]
wv_dict = {}
for wv in wv_array:
try:
2023-06-21 19:49:00 -03:00
wv_dict[wv[0]][wv[1]][wv[2]] = wv[3]
2023-02-07 13:06:02 +05:30
except:
try:
2023-06-21 19:49:00 -03:00
wv_dict[wv[0]][wv[1]] = {wv[2]: wv[3]}
2023-02-07 13:06:02 +05:30
except:
2023-06-21 19:49:00 -03:00
try:
wv_dict[wv[0]] = {wv[1]: {wv[2]: wv[3]}}
except:
pass
2023-02-07 13:06:02 +05:30
simd_wave_filenames[key] = wv_dict
2023-06-21 19:49:00 -03:00
if MPI_COMM is not None:
se_filenames = MPI_COMM.gather(se_filenames, root=0)
simd_wave_filenames = MPI_COMM.gather(simd_wave_filenames, root=0)
if mpi_root:
se_filenames = [e for elem in se_filenames for e in elem]
simd_wave_filenames = {k:v for smf in simd_wave_filenames for k,v in smf.items()}
if mpi_root:
JSON_GLOBAL_DICTIONARY['filenames.json'] = Readable({"wave_filenames": simd_wave_filenames,
"se_filenames": se_filenames,
2023-05-02 05:17:47 -03:00
"global_begin_time": int(se_time_begin),
"gfxv": gfxv})
2023-02-07 13:06:02 +05:30
if pic_thread is not None:
pic_thread.join()
for k, v in return_dict.items():
JSON_GLOBAL_DICTIONARY[k] = v
2023-02-07 13:06:02 +05:30
if bDumpOnly == False:
2023-06-21 19:49:00 -03:00
if MPI_COMM is not None:
JSON_GLOBAL_DICTIONARY = MPI_COMM.gather(JSON_GLOBAL_DICTIONARY, root=0)
if not mpi_root:
quit()
JSON_GLOBAL_DICTIONARY = {k:v for smf in JSON_GLOBAL_DICTIONARY for k,v in smf.items()}
JSON_GLOBAL_DICTIONARY['live.json'] = Readable({'live': 1})
if args.ports:
assign_ports(args.ports)
print('serving at ports: {0},{1}'.format(PORT, WebSocketPort))
2023-02-07 13:06:02 +05:30
try:
2023-06-21 19:49:00 -03:00
PROCS = [Process(target=run_server, args=[drawinfo]), Process(target=run_websocket)]
2023-02-07 13:06:02 +05:30
for p in PROCS:
p.start()
for p in PROCS:
p.join()
except KeyboardInterrupt:
print("Exitting.")
else:
2023-06-21 19:49:00 -03:00
os.makedirs('ui/', exist_ok=True)
if mpi_root:
JSON_GLOBAL_DICTIONARY['live.json'] = Readable({'live': 0})
os.system('cp ' + os.path.join(os.path.abspath(os.path.dirname(__file__)),'ui') + '/* ui/' )
for k, v in JSON_GLOBAL_DICTIONARY.items():
with open(os.path.join('ui',k), 'w' if '.json' in k else 'wb') as f:
f.write(v.read())