Making ATT work with Profilerv2

Change-Id: Ic9334aa80e40faaaf5c1a79ba37dbe52e8d31253


[ROCm/rocprofiler commit: 03c305dbd4]
Этот коммит содержится в:
gobhardw
2023-02-07 13:06:02 +05:30
коммит произвёл Ammar ELWazir
родитель f7772fb704
Коммит 4f742d346b
28 изменённых файлов: 3783 добавлений и 24 удалений
+91 -2
Просмотреть файл
@@ -471,7 +471,7 @@ typedef enum {
/**
* Represents a ATT tracing record (Not available yet)
*/
ROCPROFILER_ATT_RECORD = 2,
ROCPROFILER_ATT_TRACER_RECORD = 2,
/**
* Represents a PC sampling record
*/
@@ -1046,6 +1046,66 @@ typedef struct {
} rocprofiler_record_spm_t;
/**
* struct to store the trace data from a shader engine.
*/
typedef struct {
void* buffer_ptr;
uint32_t buffer_size;
} rocprofiler_record_se_att_data_t;
/**
* ATT tracing record structure.
* This will represent all the information reported by the
* ATT tracer such as the kernel and its thread trace data.
* This record can be flushed to the user using
* ::rocmtools_buffer_callback_t
*/
typedef struct {
/**
* ROCMtool General Record base header to identify the id and kind of every
* record
*/
rocprofiler_record_header_t header;
/**
* Kernel Identifier to be used by the user to get the kernel info using
* ::rocmtools_query_kernel_info
*/
rocprofiler_kernel_id_t kernel_id;
/**
* Agent Identifier to be used by the user to get the Agent Information using
* ::rocmtools_query_agent_info
*/
rocprofiler_agent_id_t gpu_id;
/**
* Queue Identifier to be used by the user to get the Queue Information using
* ::rocmtools_query_agent_info
*/
rocprofiler_queue_id_t queue_id;
/**
* kernel properties, including the grid size, work group size,
* registers count, wave size and completion signal
*/
rocprofiler_kernel_properties_t kernel_properties;
/**
* Thread id
*/
rocprofiler_thread_id_t thread_id;
/**
* Queue Index - packet index in the queue
*/
rocprofiler_queue_index_t queue_idx;
/**
* ATT data output from each shader engine.
*/
rocprofiler_record_se_att_data_t* shader_engine_data;
/**
* The count of the shader engine ATT data
*/
uint64_t shader_engine_data_count;
} rocprofiler_record_att_tracer_t;
/** @} */
@@ -1721,7 +1781,7 @@ typedef enum {
/**
* ATT Tracing. (Not Yet Supported)
*/
ROCPROFILER_ATT_TRACE = 4,
ROCPROFILER_ATT_TRACE_COLLECTION = 4,
/**
* SPM collection. (Not Yet Supported)
*/
@@ -1764,6 +1824,31 @@ typedef enum {
typedef const char* rocprofiler_hip_function_name_t;
typedef const char* rocprofiler_hsa_function_name_t;
// ATT tracing parameter names
typedef enum {
ROCPROFILER_ATT_COMPUTE_UNIT_TARGET = 0,
ROCPROFILER_ATT_VM_ID_MASK = 1,
ROCPROFILER_ATT_MASK = 2,
ROCPROFILER_ATT_TOKEN_MASK = 3,
ROCPROFILER_ATT_TOKEN_MASK2 = 4,
ROCPROFILER_ATT_SE_MASK = 5,
ROCPROFILER_ATT_SAMPLE_RATE = 6,
ROCPROFILER_ATT_PERF_MASK = 240,
ROCPROFILER_ATT_PERF_CTRL = 241,
ROCPROFILER_ATT_PERFCOUNTER = 242,
ROCPROFILER_ATT_PERFCOUNTER_NAME = 243,
ROCPROFILER_ATT_MAXVALUE
} rocprofiler_att_parameter_name_t;
// att tracing parameters object
typedef struct {
rocprofiler_att_parameter_name_t parameter_name;
union {
uint32_t value;
const char* counter_name;
};
} rocprofiler_att_parameter_t;
/**
* Filter Data Type
* filter data will be used to report required and optional filters for the
@@ -1822,6 +1907,10 @@ typedef union {
* Counters to profile
*/
const char** counters_names;
/**
* att parameters
*/
rocprofiler_att_parameter_t* att_parameters;
/**
* spm counters parameters
*/
+1
Просмотреть файл
@@ -23,3 +23,4 @@
add_subdirectory(file)
add_subdirectory(perfetto)
add_subdirectory(ctf)
add_subdirectory(att)
+56
Просмотреть файл
@@ -0,0 +1,56 @@
# ###############################################################################
# # Copyright (c) 2022 Advanced Micro Devices, Inc.
# #
# # Permission is hereby granted, free of charge, to any person obtaining a copy
# # of this software and associated documentation files (the "Software"), to
# # deal in the Software without restriction, including without limitation the
# # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# # sell copies of the Software, and to permit persons to whom the Software is
# # furnished to do so, subject to the following conditions:
# #
# # The above copyright notice and this permission notice shall be included in
# # all copies or substantial portions of the Software.
# #
# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# # IN THE SOFTWARE.
# ###############################################################################
# Building att plugin library
file(GLOB ROCMTOOLS_UTIL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/utils/helper.cpp)
file(GLOB FILE_SOURCES att.cpp)
add_library(att_plugin SHARED ${FILE_SOURCES} ${ROCMTOOLS_UTIL_SRC_FILES})
set_target_properties(att_plugin PROPERTIES
CXX_VISIBILITY_PRESET hidden
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../exportmap
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
target_compile_definitions(att_plugin
PRIVATE HIP_PROF_HIP_API_STRING=1 __HIP_PLATFORM_HCC__=1)
target_include_directories(att_plugin PRIVATE ${PROJECT_SOURCE_DIR}/inc ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
target_link_options(att_plugin PRIVATE -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exportmap -Wl,--no-undefined)
target_link_libraries(att_plugin PRIVATE ${ROCPROFILER_TARGET} systemd hsa-runtime64::hsa-runtime64 stdc++fs)
install(TARGETS att_plugin LIBRARY
DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}
COMPONENT runtime)
configure_file(att.py att/att.py COPYONLY)
configure_file(trace_view.py att/trace_view.py COPYONLY)
#configure_file(t.db att/t.db COPYONLY)
configure_file(ui/index.html att/ui/index.html COPYONLY)
configure_file(ui/logo.svg att/ui/logo.svg COPYONLY)
configure_file(ui/styles.css att/ui/styles.css COPYONLY)
#configure_file(ui/trace.json att/ui/trace.json COPYONLY)
install(DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/att
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/rocprofiler
USE_SOURCE_PERMISSIONS
COMPONENT runtime)
+189
Просмотреть файл
@@ -0,0 +1,189 @@
/* Copyright (c) 2022 Advanced Micro Devices, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */
#include <cxxabi.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <experimental/filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <optional>
#include <ostream>
#include <sstream>
#include <string>
#include <hsa/hsa.h>
#include <mutex>
#include <sys/stat.h>
#include "rocprofiler.h"
#include "rocprofiler_plugin.h"
#include "../utils.h"
namespace {
class att_plugin_t {
public:
att_plugin_t() {}
std::mutex writing_lock;
bool is_valid_{true};
inline bool att_file_exists(const std::string& name) {
struct stat buffer;
return stat(name.c_str(), &buffer) == 0;
}
bool IsValid() const { return is_valid_; }
void FlushATTRecord(const rocprofiler_record_att_tracer_t* att_tracer_record,
rocprofiler_session_id_t session_id, rocprofiler_buffer_id_t buffer_id) {
std::lock_guard<std::mutex> lock(writing_lock);
if (!att_tracer_record) {
printf("No att data buffer received\n");
return;
}
size_t name_length;
CHECK_ROCMTOOLS(rocprofiler_query_kernel_info_size(ROCPROFILER_KERNEL_NAME,
att_tracer_record->kernel_id, &name_length));
const char* kernel_name_c = static_cast<const char*>(malloc(name_length * sizeof(char)));
CHECK_ROCMTOOLS(rocprofiler_query_kernel_info(ROCPROFILER_KERNEL_NAME,
att_tracer_record->kernel_id, &kernel_name_c));
std::string name_demangled = rocmtools::truncate_name(rocmtools::cxx_demangle(kernel_name_c));
// Get the number of shader engine traces
int se_num = att_tracer_record->shader_engine_data_count;
// Find if this filename already exists. If so, increment vname.
int file_iteration = -1;
bool bIncrementVersion = true;
while(bIncrementVersion) {
file_iteration += 1;
std::string fss = name_demangled+"_v"+std::to_string(file_iteration);
bIncrementVersion = att_file_exists(fss + "_kernel.txt");
}
std::string fname = name_demangled+"_v"+std::to_string(file_iteration)+"_kernel.txt";
std::ofstream(fname.c_str()) << name_demangled << ": " << kernel_name_c << '\n';
// iterate over each shader engine att trace
for (int i = 0; i < se_num; i++) {
if (!att_tracer_record->shader_engine_data &&
!att_tracer_record->shader_engine_data[i].buffer_ptr)
continue;
printf("--------------collecting data for shader_engine %d---------------\n", i);
rocprofiler_record_se_att_data_t* se_att_trace = &att_tracer_record->shader_engine_data[i];
uint32_t size = se_att_trace->buffer_size;
const char* data_buffer_ptr = reinterpret_cast<char*>(se_att_trace->buffer_ptr);
// dump data in binary format
std::ostringstream oss;
oss << name_demangled << "_v" << file_iteration << "_se" << i << ".att";
std::ofstream out(oss.str().c_str(), std::ios::binary);
if (out.is_open()) {
out.write((char*)data_buffer_ptr, size);
out.close();
} else {
std::cerr << "\t" << __FUNCTION__ << " Failed to open file: " << oss.str().c_str() << '\n';
}
}
}
int WriteBufferRecords(const rocprofiler_record_header_t* begin,
const rocprofiler_record_header_t* end, rocprofiler_session_id_t session_id,
rocprofiler_buffer_id_t buffer_id) {
while (begin < end) {
if (!begin) return 0;
switch (begin->kind) {
case ROCPROFILER_PROFILER_RECORD:
case ROCPROFILER_TRACER_RECORD:
case ROCPROFILER_PC_SAMPLING_RECORD:
case ROCPROFILER_SPM_RECORD:
printf("Invalid record Kind: %d", begin->kind);
break;
case ROCPROFILER_ATT_TRACER_RECORD: {
rocprofiler_record_att_tracer_t* att_record = const_cast<rocprofiler_record_att_tracer_t*>(
reinterpret_cast<const rocprofiler_record_att_tracer_t*>(begin));
FlushATTRecord(att_record, session_id, buffer_id);
break;
}
}
rocprofiler_next_record(begin, &begin, session_id, buffer_id);
}
return 0;
}
private:
};
att_plugin_t* att_plugin = nullptr;
} // namespace
ROCPROFILER_EXPORT int rocprofiler_plugin_initialize(uint32_t rocprofiler_major_version,
uint32_t rocprofiler_minor_version) {
if (rocprofiler_major_version != ROCPROFILER_VERSION_MAJOR ||
rocprofiler_minor_version < ROCPROFILER_VERSION_MINOR)
return -1;
if (att_plugin != nullptr) return -1;
att_plugin = new att_plugin_t();
if (att_plugin->IsValid()) return 0;
// The plugin failed to initialied, destroy it and return an error.
delete att_plugin;
att_plugin = nullptr;
return -1;
}
ROCPROFILER_EXPORT void rocprofiler_plugin_finalize() {
if (!att_plugin) return;
delete att_plugin;
att_plugin = nullptr;
}
ROCPROFILER_EXPORT int rocprofiler_plugin_write_buffer_records(const rocprofiler_record_header_t* begin,
const rocprofiler_record_header_t* end,
rocprofiler_session_id_t session_id,
rocprofiler_buffer_id_t buffer_id) {
if (!att_plugin || !att_plugin->IsValid()) return -1;
return att_plugin->WriteBufferRecords(begin, end, session_id, buffer_id);
}
ROCPROFILER_EXPORT int rocprofiler_plugin_write_record(rocprofiler_record_tracer_t record,
rocprofiler_session_id_t session_id) {
if (!att_plugin || !att_plugin->IsValid()) return -1;
if (record.header.id.handle == 0) return 0;
return 0;
}
Исполняемый файл
+523
Просмотреть файл
@@ -0,0 +1,523 @@
#!/usr/bin/env python3
import sys
if sys.version_info[0] < 3:
raise Exception("Must be using Python 3")
import os
import argparse
from pathlib import Path
from struct import *
from ctypes import *
import ctypes
from copy import deepcopy
from trace_view import view_trace
import sys
import glob
import numpy as np
import matplotlib.pyplot as plt
import json
class PerfEvent(ctypes.Structure):
_fields_ = [
('time', c_uint64),
('event0', c_uint16),
('event1', c_uint16),
('event2', c_uint16),
('event3', c_uint16),
('cu', c_uint8),
('bank', c_uint8),
]
def toTuple(self):
return (int(self.time), int(self.event0), int(self.event1),
int(self.event2), int(self.event3), int(self.cu), int(self.bank))
class CodeWrapped(ctypes.Structure):
""" Matches CodeWrapped on the python side """
_fields_ = [('line', ctypes.c_char_p),
('loc', ctypes.c_char_p),
('value', ctypes.c_int),
('to_line', ctypes.c_int),
('index', ctypes.c_int),
('line_num', ctypes.c_int)]
class KvPair(ctypes.Structure):
""" Matches pair<int, int> = (key, value) on the python side """
_fields_ = [('key', ctypes.c_int),
('value', ctypes.c_int)]
class ReturnAssemblyInfo(ctypes.Structure):
""" Matches ReturnAssemblyInfo on the python side """
_fields_ = [('code', POINTER(CodeWrapped)),
('jumps', POINTER(KvPair)),
('code_len', ctypes.c_int),
('jumps_len', ctypes.c_int)]
class Wave(ctypes.Structure):
_fields_ = [
('simd', ctypes.c_uint64),
('wave_id', ctypes.c_uint64),
('begin_time', ctypes.c_uint64), # Begin and end cycle
('end_time', ctypes.c_uint64),
# total VMEM/FLAT/LDS/SMEM instructions issued
# total issued memory instructions
('num_mem_instrs', ctypes.c_uint64),
# total issued instructions (compute + memory)
('num_issued_instrs', ctypes.c_uint64),
('num_valu_instrs', ctypes.c_uint64),
('num_valu_stalls', ctypes.c_uint64),
# VMEM Pipeline: instrs and stalls
('num_vmem_instrs', ctypes.c_uint64),
('num_vmem_stalls', ctypes.c_uint64),
# FLAT instrs and stalls
('num_flat_instrs', ctypes.c_uint64),
('num_flat_stalls', ctypes.c_uint64),
# LDS instr and stalls
('num_lds_instrs', ctypes.c_uint64),
('num_lds_stalls', ctypes.c_uint64),
# SCA instrs stalls
('num_salu_instrs', ctypes.c_uint64),
('num_smem_instrs', ctypes.c_uint64),
('num_salu_stalls', ctypes.c_uint64),
('num_smem_stalls', ctypes.c_uint64),
# Branch
('num_branch_instrs', ctypes.c_uint64),
('num_branch_taken_instrs', ctypes.c_uint64),
('num_branch_stalls', ctypes.c_uint64),
('timeline_string', ctypes.c_char_p),
('instructions_string', ctypes.c_char_p)]
class ReturnInfo(ctypes.Structure):
_fields_ = [('num_waves', ctypes.c_uint64),
('wavedata', POINTER(Wave)),
('num_events', ctypes.c_uint64),
('perfevents', POINTER(PerfEvent))]
try: # For build dir
path_to_parser = os.path.abspath('/usr/lib/hsa-amd-aqlprofile/librocprofv2_att.so')
SO = CDLL(path_to_parser)
except: # For installed dir
path_to_parser = os.path.abspath('/usr/local/lib/hsa-amd-aqlprofile/librocprofv2_att.so')
SO = CDLL(path_to_parser)
SO.AnalyseBinary.restype = ReturnInfo
SO.AnalyseBinary.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_bool]
SO.wrapped_parse_binary.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
SO.wrapped_parse_binary.restype = ReturnAssemblyInfo
def parse_binary(filename, kernel=None):
if kernel is None or kernel == '':
kernel = ctypes.c_char_p(0)
print('Parsing all kernels')
else:
with open(glob.glob(kernel)[0], 'r') as file:
kernel = file.readlines()
print('Parsing kernel:', kernel[0].split(': ')[0])
kernel = kernel[0].split(': ')[1].split('.kd')[0]
kernel = str(kernel).encode('utf-8')
info = SO.wrapped_parse_binary(str(filename).encode('utf-8'), kernel)
code = []
for k in range(info.code_len):
code_entry = info.code[k]
# copy string memory from C++
line = deepcopy(code_entry.line.decode("utf-8"))
loc = deepcopy(code_entry.loc.decode("utf-8"))
# Transform empty entries back to python's None
to_line = int(code_entry.to_line) if (code_entry.to_line >= 0) else None
loc = loc if len(loc) > 0 else None
code.append((line, int(code_entry.value), to_line, loc,
int(code_entry.index), int(code_entry.line_num)))
jumps = {}
for k in range(info.jumps_len):
jumps[info.jumps[k].key] = info.jumps[k].value
return code, jumps
def getWaves(filename, target_cu, verbose):
info = SO.AnalyseBinary(filename.encode('utf-8'), target_cu, verbose)
waves = [info.wavedata[k] for k in range(info.num_waves)]
events = [deepcopy(info.perfevents[k]) for k in range(info.num_events)]
for wave in waves:
wave.timeline = deepcopy(wave.timeline_string.decode("utf-8"))
wave.instructions = deepcopy(wave.instructions_string.decode("utf-8"))
return waves, events
def persist(output_ui, trace_file, SIMD):
trace = Path(trace_file).name
simds, waves = [], []
begin_time, end_time, timeline, instructions = [], [], [], []
mem_ins, issued_ins, valu_ins, valu_stalls = [], [], [], []
vmem_ins, vmem_stalls, flat_ins, flat_stalls = [], [], [], []
lds_ins, lds_stalls, salu_ins, salu_stalls = [], [], [], []
smem_ins, smem_stalls, br_ins, br_taken_ins, br_stalls = [], [], [], [], []
for wave in SIMD:
simds.append(wave.simd)
waves.append(wave.wave_id)
begin_time.append(wave.begin_time)
end_time.append(wave.end_time)
mem_ins.append(wave.num_mem_instrs)
issued_ins.append(wave.num_issued_instrs)
valu_ins.append(wave.num_valu_instrs)
valu_stalls.append(wave.num_valu_stalls)
vmem_ins.append(wave.num_vmem_instrs)
vmem_stalls.append(wave.num_vmem_stalls)
flat_ins.append(wave.num_flat_instrs)
flat_stalls.append(wave.num_flat_stalls)
lds_ins.append(wave.num_lds_instrs)
lds_stalls.append(wave.num_lds_stalls)
salu_ins.append(wave.num_salu_instrs)
salu_stalls.append(wave.num_salu_stalls)
smem_ins.append(wave.num_smem_instrs)
smem_stalls.append(wave.num_smem_stalls)
br_ins.append(wave.num_branch_instrs)
br_taken_ins.append(wave.num_branch_taken_instrs)
br_stalls.append(wave.num_branch_stalls)
timeline.append(wave.timeline)
instructions.append(wave.instructions)
#df = pd.DataFrame({
df = {
'name': [trace for _ in range(len(begin_time))],
'id': [i for i in range(len(begin_time))],
'simd': simds,
'wave_slot': waves,
'begin_time': begin_time,
'end_time': end_time,
'mem_ins': mem_ins,
'issued_ins': issued_ins,
'valu_ins': valu_ins,
'valu_stalls': valu_stalls,
'vmem_ins': vmem_ins,
'vmem_stalls': vmem_stalls,
'flat_ins': flat_ins,
'flat_stalls': flat_stalls,
'lds_ins': lds_ins,
'lds_stalls': lds_stalls,
'salu_ins': salu_ins,
'salu_stalls': salu_stalls,
'smem_ins': smem_ins,
'smem_stalls': smem_stalls,
'br_ins': br_ins,
'br_taken_ins': br_taken_ins,
'br_stalls': br_stalls,
'timeline': timeline,
'instructions': instructions,
}#)
#[print(d) for c, d in df.iterrows()]; quit()
return df
def mem_max(array):
mem_dict = {}
for SE in array:
for wave in SE:
for inst in wave:
try:
mem_dict[inst[0]][0] = max(mem_dict[inst[0]][0], inst[1])
except:
mem_dict[inst[0]] = inst[1:]
assert(mem_dict[inst[0]][1] == inst[2])
return mem_dict
def lgk(count):
return 'lgkmcnt({0})'.format(count)
def vmc(count):
return 'vmcnt({0})'.format(count)
def both_cnt(count):
return lgk(count)+' '+vmc(count)
def insert_waitcnt(flight_count, assembly_code):
flight_count = mem_max(flight_count)
for key in sorted(flight_count):
line_n = key
issue_amount, waitcnt_amount, = flight_count[key]
if 'vmcnt' in assembly_code[line_n] and 'lgkmcnt' in assembly_code[line_n]:
counter_type = both_cnt
elif 'vmcnt' in assembly_code[line_n]:
counter_type = vmc
elif 'lgkmcnt' in assembly_code[line_n]:
counter_type = lgk
else:
print('Error: Line mismatch')
exit(-1)
for count in range(waitcnt_amount+1, issue_amount):
print('Inserted line: '+str(line_n))
as_index = line_n - count/(issue_amount+1)
assembly_code[as_index] = \
'\ts_waitcnt {0}\t\t; Timing analysis.'.format(counter_type(count))
as_index += 0.5/(issue_amount+1)
assembly_code[as_index] = '\ts_nop 0\t\t\t\t\t\t; Counters: '+str(issue_amount)
return assembly_code
def Copy_Files(output_ui):
curpath = os.path.dirname(os.path.abspath(__file__))
outpath = output_ui+'/ui/'
os.makedirs(outpath, exist_ok=True)
os.system('cp '+curpath+'/ui/* '+outpath)
def get_delta_time(events):
for begin in range(len(events)):
tg_cu = events[begin].cu
for e in range(begin+1,len(events)):
if events[e].cu == tg_cu:
return events[e].time-events[begin].time
return 1
def num_cus(EVENTS):
cus = 0
for events in EVENTS:
for e in events:
cus = max(cus, e.cu)
return cus+1
def draw_wave_metrics(selections, normalize):
global PIC_SAVE_FOLDER
global EVENTS
global EVENT_NAMES
#event_names = ['Busy CUs', 'Occupancy', 'Eligible waves', 'Waves waiting']
with open(PIC_SAVE_FOLDER+'counters.json', 'w') as f:
f.write(json.dumps({"counters": EVENT_NAMES}))
plt.figure(figsize=(15,3))
delta_time = int(0.5+np.mean([get_delta_time(events) for events in EVENTS]))
maxtime = np.max([np.max([e.time for e in events]) for events in EVENTS])+1
event_timeline = np.zeros((16, maxtime), dtype=np.int32)
print('Delta:', delta_time)
print('Max_cycles:', maxtime)
kernsize = 2*(delta_time//8)+1
trim = max(maxtime//5000,1)
cycles = 4*np.arange(maxtime)[::trim]
kernel = np.asarray([np.exp(-abs(k/kernsize)**2) for k in range(-kernsize*3,kernsize*3+1)])
kernel /= np.sum(kernel)*len(EVENTS)*delta_time#*5.12 # SEslots/100%
for events in EVENTS:
for e in range(len(events)-1):
bk = events[e].bank*4
start = events[e].time
end = start+delta_time
event_timeline[bk:bk+4, start:end] += np.asarray(events[e].toTuple()[1:5])[:, None]
start = events[-1].time
event_timeline[bk:bk+4, start:start+delta_time] += \
np.asarray(events[-1].toTuple()[1:5])[:, None]
event_timeline = [np.convolve(e, kernel)[3*kernsize:-3*kernsize] for e in event_timeline]
if normalize:
event_timeline = [100*e/max(e.max(), 1E-5) for e in event_timeline]
#event_timeline[0] = np.clip(event_timeline[0]*8.5, 0, 100) #CC rate
colors = ['blue', 'green', 'gray', 'red', 'orange', 'cyan', 'black', 'darkviolet',
'yellow', 'darkred', 'pink', 'lime', 'gold', 'tan', 'aqua', 'olive']
[plt.plot(cycles, e[::trim], '-', label=n, color=c)
for e, n, c, sel in zip(event_timeline, EVENT_NAMES, colors, selections) if sel]
plt.legend()
if normalize:
plt.ylabel('As % of maximum')
else:
plt.ylabel('Value')
plt.subplots_adjust(left=0.05, right=1, top=1, bottom=0.07)
plt.savefig(PIC_SAVE_FOLDER+'timeline.png', dpi=150)
#plt.show()
def draw_wave_states(selections, normalize):
global TIMELINES
global PIC_SAVE_FOLDER
plot_indices = [1, 2, 3, 4]
STATES = [['Empty', 'Idle', 'Exec', 'Wait', 'Stall'][k] for k in plot_indices]
colors = [['gray', 'orange', 'green', 'red', 'blue'][k] for k in plot_indices]
plt.figure(figsize=(15,3))
maxtime = max([np.max((TIMELINES[k]!=0)*np.arange(0,TIMELINES[k].size)) for k in plot_indices])
timelines = [deepcopy(TIMELINES[k][:maxtime]) for k in plot_indices]
timelines = [np.pad(t, [0, maxtime-t.size]) for t in timelines]
if normalize:
timelines = np.array(timelines) / np.maximum(np.sum(timelines,0)*1E-2,1E-7)
kernsize = maxtime//120+3
trim = max(maxtime//5000,1)
cycles = np.arange(timelines[0].size)[::trim]
kernel = np.asarray([np.exp(-abs(10*k/kernsize)) for k in range(-kernsize//2,kernsize//2+1)])
kernel /= np.sum(kernel)
timelines = [np.convolve(time, kernel)[kernsize//2:-kernsize//2][::trim] for time in timelines]
with open(PIC_SAVE_FOLDER+'counters.json', 'w') as f:
f.write(json.dumps({"counters": STATES}))
[plt.plot(cycles, t, label='State '+s, linewidth=1.1, color=c)
for t, s, c, sel in zip(timelines, STATES, colors, selections) if sel]
plt.legend()
if normalize:
plt.ylabel('Waves state %')
else:
plt.ylabel('Waves state total')
plt.ylim(-1)
plt.xlim(-maxtime//200, maxtime+maxtime//200)
plt.subplots_adjust(left=0.05, right=1, top=1, bottom=0.07)
plt.savefig(PIC_SAVE_FOLDER+'timeline.png', dpi=150)
def GeneratePIC(selections=[True for k in range(4)], normalize=True):
if len(EVENTS) > 0 and np.sum([len(e) for e in EVENTS]) > 32:
draw_wave_metrics(selections, normalize)
else:
draw_wave_states(selections, normalize)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("assembly_code", help="Path of the assembly code")
parser.add_argument("--trace_file", help="Filter for trace files", default=None, type=str)
parser.add_argument("-o", "--output_ui", help="Output Folder", default='/dev/shm/attplugin/')
parser.add_argument("-k", "--att_kernel", help="Kernel file", type=str, default='*_kernel.txt')
parser.add_argument("-w", "--wave_id", help="wave id")
parser.add_argument("-p", "--ports", help="Server and websocket ports, default: 8000,18000")
parser.add_argument("--target_cu", help="Collected target CU id{0-15}", type=int, default=None)
parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument("-g", "--genasm",
help="Generate post-processed asm file at this path", type=str, default="")
args = parser.parse_args()
global EVENT_NAMES
with open(os.getenv("COUNTERS_PATH"), 'r') as f:
lines = [l.split('//')[0] for l in f.readlines()]
EVENT_NAMES = []
clean = lambda x: x.split('=')[1].split(' ')[0].split('\n')[0]
for line in lines:
if 'PERFCOUNTER_ID=' in line:
EVENT_NAMES += ['id: '+clean(line)]
elif args.target_cu is None and 'att: TARGET_CU' in line:
args.target_cu = int(clean(line))
print('Target CU set to:', args.target_cu)
for line in lines:
if 'PERFCOUNTER=' in line:
EVENT_NAMES += [clean(line).split('SQ_')[1].lower()]
if args.target_cu is None:
args.target_cu = 1
# Assembly parsing
path = Path(args.assembly_code)
if not path.is_file():
print("Invalid assembly_code('{0}')!".format(args.assembly_code))
sys.exit(1)
att_kernel = glob.glob(args.att_kernel)
if len(att_kernel) == 0:
print('Could not find att output kernel:', args.att_kernel)
exit(1)
elif len(att_kernel) > 1:
print('Found multiple kernel matching given filters:')
for n, k in enumerate(att_kernel):
print('\t', n, '->', k)
bValid = False
while bValid == False:
try:
args.att_kernel = att_kernel[int(input("Please select number: "))]
bValid = True
except KeyboardInterrupt:
exit(0)
except:
print('Invalid option.')
else:
args.att_kernel = att_kernel[0]
print('Att kernel:', args.att_kernel)
code, jumps = parse_binary(args.assembly_code, args.att_kernel)
# Trace Parsing
if args.trace_file is None:
filenames = glob.glob(args.att_kernel.split('_kernel.txt')[0]+'*.att')
assert(len(filenames) > 0)
else:
filenames = glob.glob(args.trace_file)
print('Trace filenames:', filenames)
Copy_Files(args.output_ui)
DBFILES = []
global TIMELINES
global EVENTS
TIMELINES = [np.zeros(int(1E4),dtype=np.int32) for k in range(5)]
EVENTS = []
for name in filenames:
SIMD, perfevents = getWaves(name, args.target_cu, args.verbose)
EVENTS.append(perfevents)
DBFILES.append( persist(args.output_ui, name, SIMD) )
for wave in SIMD:
time_acc = 0
tuples1 = wave.timeline.split('(')
tuples2 = [t.split(')')[0].split(',') for t in tuples1 if t != '']
tuples3 = [(int(t[0]),int(t[1])) for t in tuples2]
for state in tuples3:
if state[1] > 1E7:
print('Warning: Time limit reached for ',state[0], state[1])
break
if time_acc+state[1] > TIMELINES[state[0]].size:
TIMELINES[state[0]] = np.hstack([
TIMELINES[state[0]],
np.zeros_like(TIMELINES[state[0]])
])
TIMELINES[state[0]][time_acc:time_acc+state[1]] += 1
time_acc += state[1]
if args.genasm and len(args.genasm) > 0:
flight_count = view_trace(args, 0, code, jumps, DBFILES, filenames, True, None)
with open(args.assembly_code, 'r') as file:
lines = file.readlines()
assembly_code = {l+1.0: lines[l][:-1] for l in range(len(lines))}
assembly_code = insert_waitcnt(flight_count, assembly_code)
with open(args.genasm, 'w') as file:
keys = sorted(assembly_code.keys())
for k in keys:
file.write(assembly_code[k]+'\n')
else:
global PIC_SAVE_FOLDER
PIC_SAVE_FOLDER = args.output_ui+"/ui/"
view_trace(args, 0, code, jumps, DBFILES, filenames, False, GeneratePIC)
Исполняемый файл
+465
Просмотреть файл
@@ -0,0 +1,465 @@
#!/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 struct import *
from collections import defaultdict
import json
import time
import webbrowser
import http.server
import socketserver
import socket
import asyncio
import websockets
from multiprocessing import *
from copy import deepcopy
PORT, WebSocketPort = 8000, 18000
SP = '\u00A0'
RS_TRACE_DEBUG = "RS_TRACE_DEBUG" in os.environ
if RS_TRACE_DEBUG:
LOG = open('./att_viewer.log', 'w')
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()
def debug_log(msg, last=False):
if RS_TRACE_DEBUG:
LOG.write(msg)
if last:
LOG.close()
def try_match_swapped(insts, code, i, line):
return insts[i+1][1] == code[line][1] and insts[i][1] == code[line+1][1]
def stitch(insts, code, jumps):
result, i, line, loopCount, N = [], 0, 0, defaultdict(int), len(insts)
SMEM_INST = []
VMEM_INST = []
FLAT_INST = []
NUM_SMEM = 0
NUM_VMEM = 0
NUM_FLAT = 0
mem_unroll = []
flight_count = []
ordering = 0 # 0 for in order, 1 for ongoing flats and 2 for SMEM
while i < N:
inst = insts[i]
if line >= len(code):
break
as_line = code[line]
if inst[1] == as_line[1]:
if line in jumps:
loopCount[line-1] += 1 # label is the previous line
matched, next = True, line + 1
num_inflight = NUM_FLAT + NUM_SMEM + NUM_VMEM
if inst[1] == 1 or inst[1] == 5: # SMEM, LDS
ordering = 2 if inst[1] == 1 else ordering
SMEM_INST.append([line, num_inflight])
NUM_SMEM += 1
elif inst[1] == 3 or (inst[1] == 4 and 'global_' in as_line[0]): # VMEM R/W
VMEM_INST.append([line, num_inflight])
NUM_VMEM += 1
elif inst[1] == 4: # FLAT
ordering = max(ordering, 1)
FLAT_INST.append([line, num_inflight])
NUM_FLAT += 1
elif inst[1] == 9 and 'waitcnt' in as_line[0]:
if 'lgkmcnt' in as_line[0]:
wait_N = int(as_line[0].split('lgkmcnt(')[1].split(')')[0])
flight_count.append([as_line[-1], num_inflight, wait_N])
if wait_N == 0:
ordering = 0
if ordering == 0:
offset = len(SMEM_INST)-wait_N
mem_unroll.append( [line, SMEM_INST[:offset]+FLAT_INST] )
SMEM_INST = SMEM_INST[offset:]
FLAT_INST = []
NUM_FLAT = 0
NUM_SMEM = 0
else:
NUM_SMEM = min(max(wait_N-NUM_FLAT, 0), NUM_SMEM)
NUM_FLAT = min(max(wait_N-NUM_SMEM, 0), NUM_FLAT)
if 'vmcnt' in as_line[0]:
wait_N = int(as_line[0].split('vmcnt(')[1].split(')')[0])
flight_count.append([as_line[-1], num_inflight, wait_N])
if wait_N == 0 and ordering != 2:
ordering = 0
if ordering == 0:
offset = len(VMEM_INST)-wait_N
mem_unroll.append( [line, VMEM_INST[:offset]+FLAT_INST] )
VMEM_INST = VMEM_INST[offset:]
FLAT_INST = []
NUM_FLAT = 0
NUM_VMEM = 0
else:
NUM_VMEM = min(max(wait_N-NUM_FLAT, 0), NUM_VMEM)
NUM_FLAT = min(max(wait_N-NUM_VMEM, 0), NUM_FLAT)
elif inst[1] == 7 and as_line[1] == 10: # jump
matched, next = True, as_line[2]
elif inst[1] == 8 and as_line[1] == 10: # next
matched, next = True, line + 1
else:
# instructions with almost same timestamp swapped
# if i+1 < N and line+1 < len(code) and inst[0] == insts[i+1][0]:
matched = False
next = line + 1
if i+1 < N and line+1 < len(code):
if try_match_swapped(insts, code, i, line):
#print('Swap:', code[line])
#print('For:', code[line+1])
#result += (*(insts[i+1]), line),
#result += (*inst, line+1),
#i, next = i+2, line+2
temp = insts[i]
insts[i] = insts[i+1]
insts[i+1] = temp
next = line
#else:
# print('Could not parse tokens:', insts[i], as_line)
if matched:
new_res = inst + (line,)
result.append(new_res)
i += 1
line = next
N = max(N, 1)
if len(result) != N:
print('Warning - Stitching rate: {'+str(len(result) * 100 / N)+'% matched')
return result, loopCount, mem_unroll, flight_count
def extract_tuple(content, num):
vals = content.split(',')
assert (len(vals) == num)
last_val = vals[-1][:-1] if vals[-1].endswith(')') else vals[-1]
vals = [vals[0][1:]] + vals[1:-1] + [last_val]
return tuple(int(val) for val in vals)
def get_top_n(stitched):
TOP_N = 10
by_line_num = defaultdict(lambda: [0, 0, 0])
for (_, _, s2i, run_time, line_num) in stitched:
entry = by_line_num[line_num]
entry[0] += 1
entry[1] += s2i
entry[2] += run_time
top_n = sorted(
[(line_num, v[0], v[1], v[2])
for (line_num, v) in by_line_num.items()],
key=lambda x: x[2] + x[3],
reverse=True)
return top_n[:TOP_N]
def rjust_html(s, n):
s = str(s)
return SP * (n-len(s)) + s if len(s) < n else s
def rjust_html_format(msg, n1, inst, n2, n3, stall):
return str(rjust_html(msg,n1)) + str(rjust_html(inst,n2)) + str(SP*n3) + str(stall)
def wave_info(df, id):
issued_ins, mem_ins = df['issued_ins'][id], df['mem_ins'][id]
valu_ins, valu_stalls = df['valu_ins'][id], df['valu_stalls'][id]
salu_ins, salu_stalls = df['salu_ins'][id], df['salu_stalls'][id]
vmem_ins, vmem_stalls = df['vmem_ins'][id], df['vmem_stalls'][id]
smem_ins, smem_stalls = df['smem_ins'][id], df['smem_stalls'][id]
flat_ins, flat_stalls = df['flat_ins'][id], df['flat_stalls'][id]
lds_ins, lds_stalls = df['lds_ins'][id], df['lds_stalls'][id]
br_ins, br_stalls = df['br_ins'][id], df['br_stalls'][id]
return 'Issued:' + str(rjust_html(issued_ins,8)) + str(SP*2) + 'Mem:' + str(mem_ins) \
+ "-" * 26 + rjust_html_format("VALU:",6,valu_ins,8,4,valu_stalls) \
+ rjust_html_format("SALU:",6,salu_ins,8,4,salu_stalls) \
+ rjust_html_format("VMEM:",6,vmem_ins,8,4,vmem_stalls) \
+ rjust_html_format("SMEM:",6,smem_ins,8,4,smem_stalls) \
+ rjust_html_format("FLAT:",6,flat_ins,8,4,flat_stalls) \
+ rjust_html_format("LDS:",6,lds_ins,8,4,lds_stalls) \
+ rjust_html_format("BR:",6,br_ins,8,4,br_stalls)
def extract_waves(waves):
result, slot2seq = [], {}
for id in waves['id']:
row = {key: waves[key][id] for key in waves.keys()}
insts, timeline = [], []
for x in row['instructions'].split('),'):
if len(x) > 0:
insts.append(extract_tuple(x, 4))
for x in row['timeline'].split('),'):
if len(x) > 0:
timeline.append(extract_tuple(x, 2))
# aggregate per wave slot
if (row['simd'], row['wave_slot']) in slot2seq:
slot = result[slot2seq[(row['simd'], row['wave_slot'])]]
last_end_time = slot[2][-1][-1]
slot[2] += (row['id'], row['begin_time'], row['end_time']),
slot[3] += insts
# filler between waves
slot[4] += (0, row['begin_time'] - last_end_time),
slot[4] += timeline
else:
slot2seq[row['simd'], row['wave_slot']] = len(result)
result.append([row['simd'], row['wave_slot'],
[(row['id'], row['begin_time'], row['end_time'])],
insts,
timeline])
return result
def extract_data(df, output_ui, se_number, code, jumps):
if len(df['id']) == 0 or len(df['instructions']) == 0 or len(df['timeline']) == 0:
return None
cu_waves = extract_waves(df)
all_filenames = []
flight_count = []
for wave_id in df['id']:
insts, timeline = [], []
if len(df['instructions'][wave_id]) == 0 or len(df['timeline'][wave_id]) == 0:
continue
for x in df['instructions'][wave_id].split('),'):
insts.append(extract_tuple(x, 4))
for x in df['timeline'][wave_id].split('),'):
timeline.append(extract_tuple(x, 2))
stitched, loopCount, mem_unroll, count = stitch(insts, code, jumps)
flight_count.append(count)
wave_entry = {
"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,
"code": code,
"waitcnt": mem_unroll
}
data_obj = {
"name": 'SE'.format(se_number),
"kernel": code[0][0],
"duration": sum(dur for (_, dur) in timeline),
"wave": wave_entry,
"simd_waves": [],
"cu_waves": cu_waves,
"loop_count": loopCount,
"top_n": get_top_n(stitched),
"websocket_port": WebSocketPort,
"generation_time": time.ctime()
}
if len(data_obj["cu_waves"]) == 0:
continue
OUT = output_ui+'/ui/se'+str(se_number)+'_sm'+str(df['simd'][wave_id])+\
'_wv'+str(df['wave_slot'][wave_id])+'.json'
with open(OUT, 'w') as f:
f.write(json.dumps(data_obj))
all_filenames.append(OUT.split('/')[-1])
return flight_count, all_filenames
def open_browser():
time.sleep(0.1)
webbrowser.open_new_tab('http://{0}:{1}'.format(IPAddr, PORT))
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):
global PICTURE_CALLBACK
if 'timeline.png?' in self.path:
selections = [int(s)!=0 for s in self.path.split('timeline.png?')[1]]
print('Sel:', selections)
PICTURE_CALLBACK(selections[1:], selections[0])
http.server.SimpleHTTPRequestHandler.do_GET(self)
class RocTCPServer(socketserver.TCPServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
def run_server():
global RS_HOME
Handler = NoCacheHTTPRequestHandler
os.chdir(RS_HOME+'/ui')
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()
print(354, data)
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]
def view_trace(args, wait, code, jumps, dbnames, att_filenames, bReturnLoc, pic_callback):
global PICTURE_CALLBACK
PICTURE_CALLBACK = pic_callback
pic_thread = Process(target=pic_callback)
pic_thread.start()
assert(len(dbnames) > 0)
global RS_HOME
output_ui = args.output_ui
RS_HOME = output_ui
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 = {}
for se_number, dbname in zip(se_numbers, dbnames):
if len(dbname['id']) == 0:
continue
count, wv_filenames = extract_data(dbname, output_ui, se_number, code, jumps)
if count is not None:
flight_count.append(count)
simd_wave_filenames[se_number] = wv_filenames
if bReturnLoc:
return flight_count
for key in simd_wave_filenames.keys():
wv_array = [[
int(s.split('_sm')[1].split('_wv')[0]),
int(s.split('_wv')[1][0]),
s
] for s in simd_wave_filenames[key]]
wv_dict = {}
for wv in wv_array:
try:
wv_dict[wv[0]][wv[1]] = wv[2]
except:
try:
wv_dict[wv[0]] = {wv[1]: wv[2]}
except:
exit(-1)
simd_wave_filenames[key] = wv_dict
with open(output_ui+'/ui/filenames.json', 'w') as f:
f.write(json.dumps({"filenames": simd_wave_filenames}))
if args.ports:
assign_ports(args.ports)
print('serving at ports: {0},{1}'.format(PORT, WebSocketPort))
if wait == 0:
try:
PROCS = [Process(target=run_server),
Process(target=open_browser),
Process(target=run_websocket)]
if pic_thread is not None:
pic_thread.join()
for p in PROCS:
p.start()
for p in PROCS:
p.join()
except KeyboardInterrupt:
print("Exitting.")
Разница между файлами не показана из-за своего большого размера Загрузить разницу
+132
Просмотреть файл
@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="240"
height="26"
viewBox="0 0 68.974872 7.4722778"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="logo.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="5.1659481"
inkscape:cx="147.89154"
inkscape:cy="75.10722"
inkscape:window-width="3840"
inkscape:window-height="2066"
inkscape:window-x="-11"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#217844;stroke:#00000f;stroke-width:0.0610255;stroke-miterlimit:1"
id="rect864"
width="37.346996"
height="6.0453367"
x="26.672634"
y="0.91105449" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.35px;font-family:Calibri;-inkscape-font-specification:Calibri;fill:#165016;stroke:#00000f;stroke-width:0.0539999;stroke-miterlimit:1;stroke-dasharray:none"
x="82.180176"
y="95.625328"
id="text3303"><tspan
sodipodi:role="line"
id="tspan3301"
style="fill:#165016;stroke-width:0.054"
x="82.180176"
y="95.625328" /></text>
<!-- <g
id="g5730"
transform="matrix(0.57568164,0,0,0.53998363,-62.239348,-52.859622)">
<g
aria-label="AMD"
id="text954"
style="font-size:6.35px;font-family:Calibri;-inkscape-font-specification:Calibri;fill:#000080;stroke:#00000f;stroke-width:0.0539999;stroke-miterlimit:1"
transform="translate(27.503837,13.598552)">
<path
d="m 89.87666,89.436026 q 0.04779,0.05463 0.06348,0.09511 0.01746,0.03646 0.0022,0.06566 -0.01528,0.0292 -0.06797,0.05628 -0.0498,0.02596 -0.139412,0.0607 -0.08962,0.03475 -0.146787,0.05026 -0.05316,0.01729 -0.08543,0.01982 -0.0305,-0.0015 -0.05168,-0.01322 -0.01829,-0.01286 -0.03994,-0.0344 l -0.673965,-0.786215 -1.555301,0.60303 0.04216,1.017881 q 0.0014,0.02938 -0.0052,0.05522 -0.0077,0.02295 -0.03103,0.04861 -0.02154,0.02165 -0.07133,0.04761 -0.0469,0.02484 -0.127848,0.05622 -0.08384,0.0325 -0.142126,0.04513 -0.05428,0.01439 -0.08525,0.0031 -0.02808,-0.01239 -0.04265,-0.04997 -0.0128,-0.04159 -0.01433,-0.11416 l -0.09264,-3.961315 q -7.66e-4,-0.03628 0.0087,-0.06324 0.01239,-0.02808 0.0426,-0.0531 0.0331,-0.02613 0.08691,-0.05032 0.05558,-0.0282 0.142303,-0.06183 0.09251,-0.03587 0.155459,-0.05362 0.06183,-0.02065 0.103895,-0.02366 0.04206,-0.003 0.07127,0.01227 0.02808,0.01239 0.05198,0.03971 z m -2.799476,-2.442912 -0.0029,0.0011 0.07829,2.114582 1.300903,-0.504394 z"
style="stroke-width:0.054"
id="path4984" />
<path
d="m 94.99296,89.362526 q -2.68e-4,0.0248 -0.01287,0.04327 -0.0126,0.01847 -0.04374,0.03054 -0.0311,0.009 -0.08078,0.01463 -0.04661,0.0088 -0.124117,0.008 -0.07131,-7.69e-4 -0.123916,-0.01064 -0.04954,-0.0067 -0.08044,-0.01637 -0.02777,-0.0127 -0.03997,-0.03144 -0.0122,-0.01874 -0.01193,-0.04354 l 0.03766,-3.494157 -0.0062,-6.7e-5 -1.467119,3.494252 q -0.0095,0.0216 -0.0283,0.0369 -0.01567,0.01533 -0.04991,0.02737 -0.0311,0.009 -0.07764,0.01157 -0.04347,0.0057 -0.105481,0.0051 -0.06511,-7.02e-4 -0.111547,-0.0074 -0.04644,-0.0067 -0.07734,-0.01634 -0.03087,-0.01274 -0.04931,-0.02844 -0.01533,-0.01567 -0.02133,-0.03434 l -1.329447,-3.524398 -0.0031,-3.4e-5 -0.03767,3.494158 q -2.67e-4,0.0248 -0.01287,0.04327 -0.0126,0.01847 -0.04374,0.03054 -0.0311,0.009 -0.08078,0.01463 -0.04971,0.0088 -0.127216,0.0079 -0.07441,-8.02e-4 -0.123916,-0.01064 -0.04954,-0.0067 -0.08044,-0.01637 -0.02777,-0.0127 -0.03997,-0.03144 -0.0091,-0.0187 -0.0088,-0.04351 l 0.03977,-3.689482 q 0.0014,-0.130217 0.07022,-0.18529 0.06881,-0.05507 0.152521,-0.05417 l 0.322442,0.0035 q 0.09921,0.0011 0.173422,0.02047 0.07421,0.0194 0.129582,0.06031 0.05537,0.04091 0.09191,0.103316 0.03654,0.06241 0.06354,0.146421 l 1.131337,2.917613 0.0155,1.67e-4 1.240374,-2.882745 q 0.03511,-0.09265 0.07611,-0.157319 0.04101,-0.06467 0.08791,-0.101377 0.05004,-0.03977 0.109116,-0.05464 0.05911,-0.01797 0.136618,-0.01713 l 0.337944,0.0036 q 0.04651,5.01e-4 0.08665,0.01644 0.04327,0.01287 0.07084,0.04417 0.0307,0.02824 0.04881,0.07494 0.01813,0.04361 0.01743,0.108714 z"
style="stroke-width:0.054"
id="path4986" />
<path
d="m 99.688647,89.106481 q -0.202131,0.480082 -0.476607,0.788407 -0.273273,0.305468 -0.610318,0.442789 -0.332985,0.135666 -0.72523,0.10845 -0.392245,-0.02722 -0.866611,-0.22694 l -0.78299,-0.329666 q -0.06573,-0.02767 -0.107689,-0.0958 -0.0379,-0.06979 0.009,-0.181233 l 1.388446,-3.297704 q 0.04692,-0.111447 0.122123,-0.130248 0.07926,-0.02046 0.144986,0.0072 l 0.837285,0.352526 q 0.480082,0.202131 0.758628,0.467433 0.279749,0.262444 0.403985,0.590616 0.128297,0.326518 0.103035,0.706129 -0.0224,0.380814 -0.198064,0.798028 z m -0.525653,-0.197768 q 0.126331,-0.300051 0.160317,-0.58852 0.03519,-0.291326 -0.04543,-0.547307 -0.07776,-0.254777 -0.276143,-0.462778 -0.198382,-0.208 -0.581304,-0.369224 l -0.500085,-0.210553 -1.211581,2.877633 0.505801,0.212959 q 0.354346,0.149191 0.634542,0.162873 0.280196,0.01368 0.520083,-0.100626 0.239887,-0.114308 0.435404,-0.354952 0.199578,-0.242298 0.358396,-0.619505 z"
style="stroke-width:0.054"
id="path4988" />
</g>
<g
aria-label="Research"
id="text3463"
style="font-size:6.35px;font-family:Calibri;-inkscape-font-specification:Calibri;fill:#165016;stroke:#00000f;stroke-width:0.0539999;stroke-miterlimit:1"
transform="translate(28.562171,13.598552)">
<path
d="m 83.86747,96.36485 q 0,0.02481 -0.0093,0.04341 -0.0093,0.0186 -0.04031,0.03101 -0.031,0.0124 -0.08682,0.0186 -0.05581,0.0062 -0.148828,0.0062 -0.08062,0 -0.133325,-0.0062 -0.04961,-0.0062 -0.08062,-0.0186 -0.031,-0.0155 -0.04961,-0.04031 -0.0155,-0.0248 -0.0279,-0.06201 l -0.36897,-0.945679 q -0.06511,-0.161231 -0.136426,-0.294556 -0.06821,-0.136426 -0.164331,-0.232544 -0.09612,-0.09922 -0.226343,-0.151928 -0.130224,-0.05581 -0.313159,-0.05581 h -0.356567 v 1.708423 q 0,0.02481 -0.0155,0.04341 -0.0124,0.0186 -0.04341,0.03101 -0.02791,0.0093 -0.08062,0.0155 -0.04961,0.0093 -0.127124,0.0093 -0.07752,0 -0.130225,-0.0093 -0.04961,-0.0062 -0.08062,-0.0155 -0.03101,-0.0124 -0.04341,-0.03101 -0.0124,-0.0186 -0.0124,-0.04341 v -3.714502 q 0,-0.120923 0.06201,-0.167432 0.06511,-0.04961 0.136426,-0.04961 h 0.852661 q 0.151928,0 0.251147,0.0093 0.10232,0.0062 0.182935,0.0155 0.232544,0.04031 0.409277,0.127124 0.179834,0.08682 0.300757,0.220141 0.120923,0.133325 0.179834,0.306958 0.06201,0.170532 0.06201,0.378272 0,0.201538 -0.05581,0.362768 -0.05271,0.15813 -0.155029,0.282154 -0.10232,0.120922 -0.244947,0.210839 -0.142626,0.08992 -0.31936,0.151929 0.09922,0.04341 0.179834,0.111621 0.08061,0.06511 0.148828,0.15813 0.07131,0.09302 0.133325,0.213941 0.06201,0.120922 0.124024,0.272851 l 0.359668,0.883667 q 0.04341,0.111621 0.05581,0.15813 0.0124,0.04341 0.0124,0.06821 z m -0.803052,-2.818433 q 0,-0.235644 -0.10542,-0.396875 -0.10542,-0.164331 -0.353467,-0.235644 -0.07751,-0.0217 -0.176733,-0.03101 -0.09612,-0.0093 -0.254248,-0.0093 h -0.449585 v 1.351856 h 0.520898 q 0.21084,0 0.362769,-0.04961 0.155029,-0.05271 0.257348,-0.142627 0.10232,-0.09302 0.148829,-0.217041 0.04961,-0.124023 0.04961,-0.269751 z"
style="stroke-width:0.054"
id="path4967" />
<path
d="m 86.850233,94.851764 q 0,0.120923 -0.06201,0.173633 -0.05891,0.04961 -0.136426,0.04961 H 84.82245 q 0,0.232544 0.04651,0.418579 0.04651,0.186035 0.155029,0.319361 0.108521,0.133325 0.282154,0.204638 0.173633,0.07131 0.42478,0.07131 0.198437,0 0.353467,-0.03101 0.155029,-0.03411 0.26665,-0.07441 0.114722,-0.04031 0.186035,-0.07131 0.07441,-0.03411 0.111621,-0.03411 0.0217,0 0.03721,0.0124 0.0186,0.0093 0.02791,0.03101 0.0093,0.0217 0.0124,0.06201 0.0062,0.03721 0.0062,0.09302 0,0.04031 -0.0031,0.07131 -0.0031,0.02791 -0.0093,0.05271 -0.0031,0.0217 -0.0155,0.04031 -0.0093,0.0186 -0.0279,0.03721 -0.0155,0.0155 -0.09922,0.05581 -0.08372,0.03721 -0.217041,0.07441 -0.133325,0.03721 -0.310059,0.06511 -0.173633,0.03101 -0.37207,0.03101 -0.344165,0 -0.604614,-0.09612 -0.257349,-0.09612 -0.434082,-0.285254 -0.176734,-0.189136 -0.266651,-0.474389 -0.08992,-0.285254 -0.08992,-0.663526 0,-0.359668 0.09302,-0.644922 0.09302,-0.288354 0.26665,-0.486792 0.176734,-0.201538 0.424781,-0.306958 0.248046,-0.10852 0.555004,-0.10852 0.328663,0 0.558106,0.10542 0.232544,0.10542 0.381372,0.285254 0.148828,0.176733 0.217041,0.418579 0.07131,0.238745 0.07131,0.511596 z m -0.514697,-0.151929 q 0.0093,-0.403076 -0.179834,-0.632519 -0.186035,-0.229444 -0.555005,-0.229444 -0.189135,0 -0.331762,0.07131 -0.142627,0.07131 -0.238745,0.189136 -0.09612,0.117822 -0.148829,0.275952 -0.05271,0.155029 -0.05891,0.325561 z"
style="stroke-width:0.054"
id="path4969" />
<path
d="m 89.380312,95.608307 q 0,0.21394 -0.08062,0.381372 -0.07751,0.167432 -0.223242,0.282153 -0.145727,0.114722 -0.347265,0.173633 -0.201539,0.05891 -0.443384,0.05891 -0.148828,0 -0.285254,-0.0248 -0.133325,-0.02171 -0.241846,-0.05581 -0.10542,-0.03721 -0.179834,-0.07441 -0.07441,-0.04031 -0.10852,-0.07131 -0.03411,-0.031 -0.04961,-0.08682 -0.0155,-0.05581 -0.0155,-0.151929 0,-0.05891 0.0062,-0.09922 0.0062,-0.04031 0.0155,-0.06511 0.0093,-0.0248 0.02481,-0.03411 0.0186,-0.0124 0.04031,-0.0124 0.03411,0 0.09922,0.04341 0.06821,0.04031 0.164332,0.08992 0.09922,0.04961 0.232543,0.09302 0.133326,0.04031 0.306958,0.04031 0.130225,0 0.235645,-0.02791 0.10542,-0.02791 0.182935,-0.08062 0.07751,-0.05581 0.117822,-0.139526 0.04341,-0.08372 0.04341,-0.198437 0,-0.117823 -0.06201,-0.198438 -0.05891,-0.08061 -0.15813,-0.142627 -0.09922,-0.06201 -0.223242,-0.10852 -0.124023,-0.04961 -0.257348,-0.10232 -0.130225,-0.05271 -0.257349,-0.117822 -0.124023,-0.06821 -0.223242,-0.164331 -0.09922,-0.09612 -0.161231,-0.229443 -0.05891,-0.133326 -0.05891,-0.319361 0,-0.164331 0.06201,-0.313159 0.06511,-0.151929 0.192236,-0.26355 0.127124,-0.114721 0.31626,-0.182934 0.192236,-0.06821 0.446484,-0.06821 0.111621,0 0.223243,0.0186 0.111621,0.0186 0.201538,0.04651 0.08992,0.0279 0.151928,0.06201 0.06511,0.03101 0.09612,0.05581 0.03411,0.02481 0.04341,0.04341 0.0124,0.0186 0.0155,0.04341 0.0062,0.0217 0.0093,0.05581 0.0062,0.03411 0.0062,0.08372 0,0.05271 -0.0062,0.09302 -0.0031,0.03721 -0.0155,0.06201 -0.0093,0.02481 -0.0248,0.03721 -0.0155,0.0093 -0.03411,0.0093 -0.02791,0 -0.08062,-0.03411 -0.05271,-0.03411 -0.136426,-0.07131 -0.08371,-0.04031 -0.198437,-0.07441 -0.111621,-0.03411 -0.257349,-0.03411 -0.130224,0 -0.229443,0.03101 -0.09922,0.0279 -0.164331,0.08371 -0.06201,0.05271 -0.09612,0.127124 -0.03101,0.07442 -0.03101,0.161231 0,0.120923 0.06201,0.204639 0.06201,0.08061 0.16123,0.142627 0.09922,0.06201 0.226343,0.111621 0.127124,0.04961 0.257348,0.102319 0.133326,0.05271 0.26045,0.117822 0.130224,0.06511 0.229443,0.15813 0.09922,0.09302 0.15813,0.223242 0.06201,0.130225 0.06201,0.310059 z"
style="stroke-width:0.054"
id="path4971" />
<path
d="m 92.4933,94.851764 q 0,0.120923 -0.06201,0.173633 -0.05891,0.04961 -0.136426,0.04961 h -1.829346 q 0,0.232544 0.04651,0.418579 0.04651,0.186035 0.15503,0.319361 0.10852,0.133325 0.282153,0.204638 0.173633,0.07131 0.42478,0.07131 0.198438,0 0.353467,-0.03101 0.155029,-0.03411 0.26665,-0.07441 0.114722,-0.04031 0.186035,-0.07131 0.07442,-0.03411 0.111622,-0.03411 0.0217,0 0.03721,0.0124 0.0186,0.0093 0.02791,0.03101 0.0093,0.0217 0.0124,0.06201 0.0062,0.03721 0.0062,0.09302 0,0.04031 -0.0031,0.07131 -0.0031,0.02791 -0.0093,0.05271 -0.0031,0.0217 -0.0155,0.04031 -0.0093,0.0186 -0.02791,0.03721 -0.0155,0.0155 -0.09922,0.05581 -0.08372,0.03721 -0.217041,0.07441 -0.133325,0.03721 -0.310059,0.06511 -0.173632,0.03101 -0.37207,0.03101 -0.344165,0 -0.604614,-0.09612 -0.257349,-0.09612 -0.434082,-0.285254 -0.176734,-0.189136 -0.26665,-0.474389 -0.08992,-0.285254 -0.08992,-0.663526 0,-0.359668 0.09302,-0.644922 0.09302,-0.288354 0.26665,-0.486792 0.176734,-0.201538 0.424781,-0.306958 0.248047,-0.10852 0.555005,-0.10852 0.328662,0 0.558105,0.10542 0.232544,0.10542 0.381372,0.285254 0.148828,0.176733 0.217041,0.418579 0.07131,0.238745 0.07131,0.511596 z m -0.514698,-0.151929 q 0.0093,-0.403076 -0.179834,-0.632519 -0.186035,-0.229444 -0.555004,-0.229444 -0.189136,0 -0.331763,0.07131 -0.142627,0.07131 -0.238745,0.189136 -0.09612,0.117822 -0.148828,0.275952 -0.05271,0.155029 -0.05891,0.325561 z"
style="stroke-width:0.054"
id="path4973" />
<path
d="m 95.373744,96.371051 q 0,0.03721 -0.02481,0.05581 -0.0248,0.0186 -0.06821,0.02791 -0.04341,0.0093 -0.127124,0.0093 -0.08062,0 -0.130225,-0.0093 -0.04651,-0.0093 -0.06821,-0.02791 -0.0217,-0.0186 -0.0217,-0.05581 v -0.279053 q -0.182935,0.195337 -0.409277,0.303858 -0.223243,0.10852 -0.47439,0.10852 -0.220142,0 -0.399976,-0.05891 -0.176733,-0.05581 -0.303857,-0.164331 -0.124023,-0.10852 -0.195337,-0.26665 -0.06821,-0.15813 -0.06821,-0.359668 0,-0.235645 0.09612,-0.409278 0.09612,-0.173632 0.275952,-0.288354 0.179834,-0.114722 0.440284,-0.170532 0.260449,-0.05891 0.58601,-0.05891 h 0.384473 v -0.217042 q 0,-0.16123 -0.03411,-0.285253 -0.03411,-0.124024 -0.111621,-0.204639 -0.07442,-0.08372 -0.195337,-0.124024 -0.120923,-0.04341 -0.297657,-0.04341 -0.189135,0 -0.341064,0.04651 -0.148828,0.04341 -0.26355,0.09922 -0.111621,0.05271 -0.189136,0.09922 -0.07441,0.04341 -0.111621,0.04341 -0.0248,0 -0.04341,-0.0124 -0.0186,-0.0124 -0.03411,-0.03721 -0.0124,-0.0248 -0.0186,-0.06201 -0.0062,-0.04031 -0.0062,-0.08682 0,-0.07751 0.0093,-0.120923 0.0124,-0.04651 0.05271,-0.08682 0.04341,-0.04031 0.145727,-0.09302 0.10232,-0.05581 0.235645,-0.09922 0.133325,-0.04651 0.291455,-0.07441 0.15813,-0.03101 0.31936,-0.03101 0.300757,0 0.511597,0.06821 0.21084,0.06821 0.341064,0.201538 0.130225,0.130224 0.189136,0.325561 0.05891,0.195337 0.05891,0.455786 z M 94.865248,95.09671 h -0.437183 q -0.210839,0 -0.365869,0.03721 -0.155029,0.03411 -0.257348,0.10542 -0.10232,0.06821 -0.151929,0.167432 -0.04651,0.09612 -0.04651,0.223242 0,0.217041 0.136426,0.347266 0.139526,0.127124 0.387573,0.127124 0.201538,0 0.372071,-0.10232 0.173632,-0.102319 0.362768,-0.313159 z"
style="stroke-width:0.054"
id="path4975" />
<path
d="m 97.94413,93.760358 q 0,0.06821 -0.0031,0.114721 -0.0031,0.04651 -0.0124,0.07441 -0.0093,0.02481 -0.02481,0.04031 -0.0124,0.0124 -0.03721,0.0124 -0.02481,0 -0.06201,-0.0124 -0.03411,-0.0155 -0.08061,-0.02791 -0.04341,-0.0155 -0.09922,-0.0279 -0.05581,-0.0124 -0.120922,-0.0124 -0.07751,0 -0.151929,0.03101 -0.07441,0.03101 -0.15813,0.102319 -0.08061,0.07131 -0.170532,0.189136 -0.08992,0.117822 -0.198438,0.288355 v 1.835546 q 0,0.02481 -0.0124,0.04341 -0.0124,0.0155 -0.04031,0.0279 -0.02791,0.0124 -0.07751,0.0186 -0.04961,0.0062 -0.127124,0.0062 -0.07441,0 -0.124024,-0.0062 -0.04961,-0.0062 -0.08061,-0.0186 -0.02791,-0.0124 -0.04031,-0.0279 -0.0093,-0.0186 -0.0093,-0.04341 v -2.790527 q 0,-0.02481 0.0093,-0.04031 0.0093,-0.0186 0.03721,-0.03101 0.02791,-0.0155 0.07131,-0.0186 0.04341,-0.0062 0.114721,-0.0062 0.06821,0 0.111622,0.0062 0.04651,0.0031 0.07131,0.0186 0.02481,0.0124 0.03411,0.03101 0.0124,0.0155 0.0124,0.04031 V 93.9836 q 0.114722,-0.167432 0.21394,-0.272852 0.10232,-0.10542 0.192237,-0.164331 0.08992,-0.06201 0.176733,-0.08372 0.08992,-0.0248 0.179834,-0.0248 0.04031,0 0.08992,0.0062 0.05271,0.0031 0.10852,0.0155 0.05581,0.0124 0.09922,0.0279 0.04651,0.0155 0.06511,0.03101 0.0186,0.0155 0.0248,0.03101 0.0062,0.0124 0.0093,0.03411 0.0062,0.0217 0.0062,0.06511 0.0031,0.04031 0.0031,0.111621 z"
style="stroke-width:0.054"
id="path4977" />
<path
d="m 100.4401,95.94317 q 0,0.05271 -0.003,0.09302 -0.003,0.03721 -0.0124,0.06511 -0.006,0.02481 -0.0186,0.04651 -0.009,0.0186 -0.0496,0.05891 -0.0372,0.03721 -0.13023,0.09612 -0.093,0.05581 -0.21084,0.102319 -0.11472,0.04341 -0.251146,0.07131 -0.136426,0.0279 -0.282153,0.0279 -0.300757,0 -0.533301,-0.09922 -0.232544,-0.09922 -0.390674,-0.288354 -0.155029,-0.192236 -0.238745,-0.468188 -0.08061,-0.279053 -0.08061,-0.641822 0,-0.412378 0.09922,-0.706933 0.10232,-0.297657 0.275952,-0.486792 0.176734,-0.189136 0.412378,-0.279053 0.238746,-0.09302 0.514698,-0.09302 0.133325,0 0.257348,0.02481 0.127124,0.02481 0.232543,0.06511 0.10542,0.04031 0.18604,0.09302 0.0837,0.05271 0.12092,0.08992 0.0372,0.03721 0.0496,0.05891 0.0155,0.0217 0.0248,0.05271 0.009,0.02791 0.0124,0.06511 0.003,0.03721 0.003,0.09302 0,0.120923 -0.0279,0.170532 -0.0279,0.04651 -0.0682,0.04651 -0.0465,0 -0.10852,-0.04961 -0.0589,-0.05271 -0.15193,-0.114722 -0.09302,-0.06201 -0.226344,-0.111621 -0.130225,-0.05271 -0.310058,-0.05271 -0.36897,0 -0.567408,0.285254 -0.195337,0.282153 -0.195337,0.821655 0,0.269751 0.04961,0.47439 0.05271,0.201538 0.151928,0.337963 0.09922,0.136426 0.241846,0.204639 0.145728,0.06511 0.331763,0.06511 0.176733,0 0.310058,-0.05581 0.133326,-0.05581 0.229442,-0.120923 0.0992,-0.06821 0.16434,-0.120923 0.0682,-0.05581 0.10542,-0.05581 0.0217,0 0.0372,0.0124 0.0155,0.0124 0.0248,0.04341 0.0124,0.02791 0.0155,0.07441 0.006,0.04341 0.006,0.10542 z"
style="stroke-width:0.054"
id="path4979" />
<path
d="m 103.52208,96.36795 q 0,0.02481 -0.0124,0.04341 -0.0124,0.0155 -0.0403,0.0279 -0.0279,0.0124 -0.0775,0.0186 -0.0496,0.0062 -0.12402,0.0062 -0.0775,0 -0.12713,-0.0062 -0.0496,-0.0062 -0.0775,-0.0186 -0.0279,-0.0124 -0.0403,-0.0279 -0.0124,-0.0186 -0.0124,-0.04341 v -1.634008 q 0,-0.238745 -0.0372,-0.384473 -0.0372,-0.145728 -0.10852,-0.251147 -0.0713,-0.10542 -0.18603,-0.161231 -0.11163,-0.05581 -0.26045,-0.05581 -0.19224,0 -0.38448,0.136425 -0.19223,0.136426 -0.40307,0.399976 v 1.950268 q 0,0.02481 -0.0124,0.04341 -0.0124,0.0155 -0.0403,0.0279 -0.0279,0.0124 -0.0775,0.0186 -0.0496,0.0062 -0.12712,0.0062 -0.0744,0 -0.12402,-0.0062 -0.0496,-0.0062 -0.0806,-0.0186 -0.0279,-0.0124 -0.0403,-0.0279 -0.009,-0.0186 -0.009,-0.04341 v -4.142382 q 0,-0.02481 0.009,-0.04341 0.0124,-0.0186 0.0403,-0.031 0.031,-0.0124 0.0806,-0.0186 0.0496,-0.0062 0.12402,-0.0062 0.0775,0 0.12712,0.0062 0.0496,0.0062 0.0775,0.0186 0.0279,0.0124 0.0403,0.031 0.0124,0.0186 0.0124,0.04341 v 1.671215 q 0.22014,-0.232543 0.44338,-0.344165 0.22324,-0.114721 0.44959,-0.114721 0.27905,0 0.46818,0.09612 0.19224,0.09302 0.31006,0.251147 0.11783,0.15813 0.16743,0.372071 0.0527,0.21084 0.0527,0.511596 z"
style="stroke-width:0.054"
id="path4981" />
</g>
</g> -->
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.1311px;font-family:Calibri;-inkscape-font-specification:Calibri;fill:#f9f9f9;stroke:#00000f;stroke-width:0.0586557;stroke-miterlimit:1"
x="27.642879"
y="5.8916035"
id="text1590"><tspan
sodipodi:role="line"
id="tspan1588"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.1311px;font-family:Calibri;-inkscape-font-specification:Calibri;fill:#f9f9f9;stroke-width:0.0586558"
x="27.642879"
y="5.8916035">MI Trace View</tspan></text>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 20 KiB

+106
Просмотреть файл
@@ -0,0 +1,106 @@
h2,h3,h4 {
text-align: center;
font-family: Calibri, Candara, Optima, Arial, 'Trebuchet MS', sans-serif;
}
ul, ol {
list-style-type: none;
padding: 0;
margin: 20px 5px;
/*font-family: Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif; font-size: 15px; font-style: normal; font-variant: normal; */
font-family: 'Courier New', monospace; font-size: 15px; font-style: normal;
}
a {
color: royalblue;
cursor: pointer;
}
div#flexbox {
display: flex;
flex-wrap: wrap;
}
div#flexbox > div {
flex: 50%;
}
div#minimap {
position: absolute;
width: 350px;
top: 340px;
display: flex;
justify-content: right;
right: 5px;
}
div#wave, div#cu_wave {
overflow:scroll;
overflow-y:hidden;
}
div#ma_code {
height: calc(100vh - 180px);
overflow: auto;
overflow-x: hidden;
display: block;
margin: 20px;
}
nav {
padding-right: 8px;
position: absolute;
top: 1rem;
right: 1rem;
background: #FFFDE3;
z-index: 5;
margin-left: 10px;
width:330px;
}
.highlight {
background-color: lightgray;
font-weight: bold;
}
.clickable {
cursor: pointer;
font-weight: 180;
}
ul li {
border-bottom: 1px dotted black;
}
.tooltip {
display: none;
position: relative;
left: 10px;
z-index: 100;
background: #333;
border: 1px solid #c0c0c0;
opacity: 0.8;
color: white;
}
li:hover .tooltip {
display: inline-block; /*block;*/
}
.loop {
margin-left: 30px;
background: lightseagreen;
}
.btn {
border: 1px solid black;
background-color: #D7D7D7;
color: black;
padding: 3px 4px;
font-size: 14px;
cursor: pointer;
border-style: ridge;
border-radius: 6px;
}
.btn:hover {
color: blue;
}
+3
Просмотреть файл
@@ -403,6 +403,9 @@ class file_plugin_t {
FlushTracerRecord(*tracer_record, session_id, buffer_id);
break;
}
case ROCPROFILER_ATT_TRACER_RECORD: {
break;
}
case ROCPROFILER_PC_SAMPLING_RECORD: {
const rocprofiler_record_pc_sample_t *pc_sampling_record =
reinterpret_cast<const rocprofiler_record_pc_sample_t *>(begin);
+51 -6
Просмотреть файл
@@ -11,7 +11,7 @@ elif [[ $ROCPROFV2_DIR == *"/rocprofiler"* ]]; then
fi
usage() {
echo -e "ROCProfiler Run Script Usage:"
echo -e "ROCProfilerV2 Run Script Usage:"
echo -e "-h | --help For showing this message"
echo -e "--list-counters For showing all available counters for the current GPUs"
if [ $RUN_FROM_BUILD == 1 ]; then
@@ -21,8 +21,8 @@ usage() {
echo -e "-ct | --clean-build-test For Running the tests after a clean build"
echo -e "-mt | --mem-test For Running the Memory Leak tests. This run requires building using -acb | --asan-clean-build option"
echo -e "-acb | --asan-clean-build For compiling with ASAN library attached"
echo -e "--install For installing rocprofiler without clean build in the default installation folder (review build.sh to know more about the default paths)"
echo -e "--clean-install For installing rocprofiler with new clean build in the default installation folder (review build.sh to know more about the default paths)"
echo -e "--install For installing ROCProfilerV2 without clean build in the default installation folder (review build.sh to know more about the default paths)"
echo -e "--clean-install For installing ROCProfilerV2 with new clean build in the default installation folder (review build.sh to know more about the default paths)"
fi
echo -e "--hip-api For Collecting HIP API Traces"
echo -e "--hip-activity For Collecting HSA API Activities Traces"
@@ -31,11 +31,18 @@ usage() {
echo -e "--roctx-trace For Collecting ROCTx Traces"
echo -e "--kernel-trace For Collecting Kernel dispatch Traces"
echo -e "--sys-trace For Collecting HIP and HSA APIs and their Activities Traces along ROCTX and Kernel Dispatch traces"
echo -e "--plugin PLUGIN_NAME For enabling a plugin (file/perfetto)"
echo -e "--plugin PLUGIN_NAME For enabling a plugin (file/perfetto/att)"
echo -e "-i | --input For adding counters file path (every line in the text file represents a counter)"
echo -e "-o | --output-file For the output file name"
echo -e "-d | --output-directory For adding output path where the output files will be saved"
echo -e "-fi | --flush-interval For adding a flush interval in milliseconds, every \"flush interval\" the buffers will be flushed"
echo -e "\n###ATT Plugin options: ###"
if [ $RUN_FROM_BUILD == 1 ]; then
ATT_PATH=$ROCPROFV2_DIR/build/plugin/att/att/att.py
else
ATT_PATH=$ROCPROFV2_DIR/../libexec/rocprofiler/att/att.py
fi
eval "python3 $ATT_PATH --help"
exit 1
}
@@ -199,6 +206,35 @@ while [ 1 ] ; do
usage
exit 1
fi
if [ "$2" = "att" ] ; then
#if [ $RUN_FROM_BUILD == 1 ]; then
# export ROCMTOOLS_ATT_PARSER=build/libatt_parser.so
#else
# export ROCMTOOLS_ATT_PARSER=$ROCPROFV2_DIR/../lib/rocprofiler/libatt_parser.so
#fi
ATT_ARGV=$3
shift
ATT_OPTIONS="Not done"
while [ "$ATT_OPTIONS" = "Not done" ]; do
if [[ "$3" = "--trace_file" ]]; then
ATT_ARGV="$ATT_ARGV $3 \"$4\""
shift
shift
elif [[ "$3" = "--genasm" || "$3" = "--target_cu" || "$3" = "-o" || "$3" == "-k" || "$3" == "--att_kernel" ]]; then
ATT_ARGV="$ATT_ARGV $3 $4"
shift
shift
else
ATT_OPTIONS="Done"
fi
done
if [ $RUN_FROM_BUILD == 1 ]; then
ATT_PATH=$ROCPROFV2_DIR/build/plugin/att/att/att.py
else
ATT_PATH=$ROCPROFV2_DIR/../libexec/rocprofiler/att/att.py
fi
fi
shift
shift
elif [[ "$1" = "-"* || "$1" = "--"* ]] ; then
@@ -214,7 +250,10 @@ PMC_LINES=()
if [ -n "$COUNTERS_PATH" ]; then
input=$COUNTERS_PATH
while IFS= read -r line || [[ -n "$line" ]]; do
# if in att mode, only add the first line
if [[ ! -n "$PMC_LINES" ]] || [[ ! -n "$ATT_ARGV" ]]; then
PMC_LINES+=( "$line" )
fi
done < $input
fi
@@ -236,7 +275,7 @@ if [ -n "$PMC_LINES" ]; then
LD_PRELOAD=$LD_PRELOAD:$ROCM_DIR/lib/librocprofiler_tool.so $*
fi
done
else
elif [ ! -n "$ATT_ARGV" ]; then
if [ $RUN_FROM_BUILD == 1 ]; then
LD_PRELOAD=$LD_PRELOAD:$ROCM_DIR/build/librocprofiler_tool.so $*
else
@@ -244,4 +283,10 @@ else
fi
fi
if [ -n "$ATT_PATH" ]; then
if [ -n "$ATT_ARGV" ]; then
eval "python3 $ATT_PATH $ATT_ARGV"
elif [ ! -n "$PMC_LINES" ]; then
echo "ATT File is required!"
fi
fi
+1
Просмотреть файл
@@ -0,0 +1 @@
att: TARGET_CU=1
+2
Просмотреть файл
@@ -150,6 +150,7 @@ file(GLOB ROCPROFILER_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB ROCPROFILER_PROFILER_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/profiler/profiler.cpp)
file(GLOB ROCPROFILER_TRACER_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/tracer/*.cpp)
file(GLOB ROCPROFILER_ROCTRACER_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/tracer/src/*.cpp)
file(GLOB ROCMTOOLS_ATT_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/att/att.cpp)
file(GLOB ROCMTOOL_CLASS_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rocmtool.cpp)
file(GLOB ROCPROFILER_SPM_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/spm/spm.cpp)
@@ -189,6 +190,7 @@ add_library(${ROCPROFILER_TARGET} SHARED
${ROCPROFILER_SRC_FILES}
${ROCMTOOL_CLASS_SRC_FILES}
${ROCPROFILER_PROFILER_SRC_FILES}
${ROCMTOOLS_ATT_SRC_FILES}
${CORE_HARDWARE_SRC_FILES}
${CORE_HSA_SRC_FILES}
${ROCPROFILER_SPM_SRC_FILES}
+142
Просмотреть файл
@@ -486,4 +486,146 @@ hsa_ven_amd_aqlprofile_profile_t* InitializeDeviceProfilingAqlPackets(
return profile;
}
// ATT
uint32_t g_output_buffer_size = 0x8000000; // 128M x 16 = 2GB
bool g_output_buffer_local = true;
// Allocate system memory accessible by both CPU and GPU
uint8_t* AllocateSysMemory(hsa_agent_t gpu_agent, size_t size, hsa_amd_memory_pool_t* cpu_pool) {
hsa_status_t status = HSA_STATUS_ERROR;
uint8_t* buffer = NULL;
size = (size + MEM_PAGE_MASK) & ~MEM_PAGE_MASK;
// if (!cpu_agents_.empty()) {
status = hsa_amd_memory_pool_allocate(*cpu_pool, size, 0, reinterpret_cast<void**>(&buffer));
// Both the CPU and GPU can access the memory
if (status == HSA_STATUS_SUCCESS) {
hsa_agent_t ag_list[1] = {gpu_agent};
status = hsa_amd_agents_allow_access(1, ag_list, NULL, buffer);
}
// }
uint8_t* ptr = (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
return ptr;
}
// Allocate memory for use by a kernel of specified size
uint8_t* AllocateLocalMemory(size_t size, hsa_amd_memory_pool_t* gpu_pool) {
hsa_status_t status = HSA_STATUS_ERROR;
uint8_t* buffer = NULL;
size = (size + MEM_PAGE_MASK) & ~MEM_PAGE_MASK;
status = hsa_amd_memory_pool_allocate(*gpu_pool, size, 0, reinterpret_cast<void**>(&buffer));
uint8_t* ptr = (status == HSA_STATUS_SUCCESS) ? buffer : NULL;
return ptr;
}
hsa_status_t Allocate(hsa_agent_t gpu_agent, hsa_ven_amd_aqlprofile_profile_t* profile,
hsa_amd_memory_pool_t* cpu_pool, hsa_amd_memory_pool_t* gpu_pool) {
profile->command_buffer.ptr =
AllocateSysMemory(gpu_agent, profile->command_buffer.size, cpu_pool);
profile->output_buffer.size = g_output_buffer_size;
profile->output_buffer.ptr = (g_output_buffer_local)
? AllocateLocalMemory(profile->output_buffer.size, gpu_pool)
: AllocateSysMemory(gpu_agent, profile->output_buffer.size, cpu_pool);
return (profile->command_buffer.ptr && profile->output_buffer.ptr) ? HSA_STATUS_SUCCESS
: HSA_STATUS_ERROR;
}
bool AllocateMemoryPools(hsa_agent_t cpu_agent, hsa_agent_t gpu_agent,
hsa_amd_memory_pool_t* cpu_pool, hsa_amd_memory_pool_t* gpu_pool) {
hsa_status_t status = hsa_amd_agent_iterate_memory_pools(cpu_agent, FindStandardPool, cpu_pool);
CHECK_HSA_STATUS("hsa_amd_agent_iterate_memory_pools(cpu_pool)", status);
status = hsa_amd_agent_iterate_memory_pools(gpu_agent, FindStandardPool, gpu_pool);
CHECK_HSA_STATUS("hsa_amd_agent_iterate_memory_pools(gpu_pool)", status);
return true;
}
// map between gpu agent handle and att_memory_pools_t
typedef std::map<uint64_t, att_memory_pools_t*> att_mem_pools_map_t;
att_mem_pools_map_t* agent_att_mem_pools_map = nullptr;
std::atomic<bool> att_map_init{false};
att_mem_pools_map_t* GetAttMemPoolsMap() {
if (!att_map_init.load(std::memory_order_relaxed)) {
agent_att_mem_pools_map = new att_mem_pools_map_t();
att_map_init.exchange(true, std::memory_order_release);
}
return agent_att_mem_pools_map;
}
att_memory_pools_t* GetAttMemPools(hsa_agent_t gpu_agent) {
auto it = GetAttMemPoolsMap()->find(gpu_agent.handle);
if (it != GetAttMemPoolsMap()->end()) {
return it->second;
}
printf("Error: att_memory_pools_t instance not found for given gpu agent handle: %lu\n",
gpu_agent.handle);
return nullptr;
}
// Generate start and stop packets for collecting ATT traces
// Also generate and return the profile object which has the PM4
// command buffer and the output buffer for retrieving the traces
hsa_ven_amd_aqlprofile_profile_t* GenerateATTPackets(
hsa_agent_t cpu_agent, hsa_agent_t gpu_agent,
std::vector<hsa_ven_amd_aqlprofile_parameter_t>& att_params, packet_t* start_packet,
packet_t* stop_packet) {
att_memory_pools_t* att_mem_pools = NULL;
auto it = GetAttMemPoolsMap()->find(gpu_agent.handle);
if (it == GetAttMemPoolsMap()->end()) {
att_mem_pools = new att_memory_pools_t;
// Allocate memory pools for cpu and gpu
AllocateMemoryPools(cpu_agent, gpu_agent, &att_mem_pools->cpu_mem_pool,
&att_mem_pools->gpu_mem_pool);
GetAttMemPoolsMap()->emplace(gpu_agent.handle, att_mem_pools);
} else
att_mem_pools = it->second;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion-null"
// Preparing the profile structure to get the packets
hsa_ven_amd_aqlprofile_profile_t* profile =
new hsa_ven_amd_aqlprofile_profile_t{gpu_agent,
HSA_VEN_AMD_AQLPROFILE_EVENT_TYPE_TRACE,
nullptr,
0,
&att_params[0],
(uint32_t)att_params.size(),
NULL,
NULL};
#pragma GCC diagnostic pop
// Check the profile buffer sizes
hsa_status_t status = hsa_ven_amd_aqlprofile_start(profile, NULL);
if (status != HSA_STATUS_SUCCESS) printf("Error: aqlprofile_start(NULL)");
// // Double output buffer size if concurrent
// if (is_concurrent) profile.output_buffer.size *= 2;
// TODO: create a separate class for memory allocations
// Maintain pools per device
// handle allocation and resource cleanup
// Allocate command and output buffers
// command buffer -> from CPU memory pool
// output buffer -> from GPU memory pool
status =
Allocate(gpu_agent, profile, &att_mem_pools->cpu_mem_pool, &att_mem_pools->gpu_mem_pool);
if (status != HSA_STATUS_SUCCESS) printf("Error: Allocate()");
// Generate start/stop/read profiling packets
status = hsa_ven_amd_aqlprofile_start(profile, start_packet);
if (status != HSA_STATUS_SUCCESS) printf("Error: aqlprofile_start");
status = hsa_ven_amd_aqlprofile_stop(profile, stop_packet);
if (status != HSA_STATUS_SUCCESS) printf("Error: aqlprofile_stop");
if (status == HSA_STATUS_ERROR) return nullptr;
return profile;
}
} // namespace Packet
+20
Просмотреть файл
@@ -55,5 +55,25 @@ hsa_amd_memory_pool_t& GetCommandPool();
hsa_amd_memory_pool_t& GetOutputPool();
hsa_ven_amd_aqlprofile_profile_t* GenerateATTPackets(
hsa_agent_t cpu_agent, hsa_agent_t gpu_agent,
std::vector<hsa_ven_amd_aqlprofile_parameter_t>& att_params, packet_t* start_packet,
packet_t* stop_packet);
uint8_t* AllocateSysMemory(hsa_agent_t gpu_agent, size_t size, hsa_amd_memory_pool_t* cpu_pool);
void get_command_buffer_map(std::map<size_t, uint8_t*> );
void get_outbuffer_map(std::map<size_t, uint8_t*> );
void initialize_pools(hsa_agent_t cpu_agent);
typedef struct {
hsa_amd_memory_pool_t cpu_mem_pool;
hsa_amd_memory_pool_t gpu_mem_pool;
} att_memory_pools_t;
att_memory_pools_t* GetAttMemPools(hsa_agent_t gpu_agent);
} // namespace Packet
#endif // SRC_CORE_HSA_PACKETS_PACKETS_GENERATOR_H_
+320 -1
Просмотреть файл
@@ -34,6 +34,8 @@
#include "src/utils/helper.h"
#define __NR_gettid 186
#define MAX_ATT_PROFILES 16
std::mutex sessions_pending_signal_lock;
namespace rocmtools {
@@ -52,6 +54,8 @@ static inline bool IsEventMatch(const hsa_ven_amd_aqlprofile_event_t& event1,
(event1.counter_id == event2.counter_id);
}
typedef std::vector<hsa_ven_amd_aqlprofile_info_data_t> att_trace_callback_data_t;
static std::mutex ksymbol_map_lock;
static std::map<uint64_t, std::string>* ksymbols;
static std::atomic<bool> ksymbols_flag{true};
@@ -234,6 +238,17 @@ hsa_status_t pmcCallback(hsa_ven_amd_aqlprofile_info_type_t info_type,
return status;
}
hsa_status_t attTraceDataCallback(hsa_ven_amd_aqlprofile_info_type_t info_type,
hsa_ven_amd_aqlprofile_info_data_t* info_data, void* data) {
hsa_status_t status = HSA_STATUS_SUCCESS;
att_trace_callback_data_t* passed_data = reinterpret_cast<att_trace_callback_data_t*>(data);
passed_data->push_back(*info_data);
// TODO: clear output buffers after copying
// either copy here or in AddattRecord
return status;
}
void AddRecordCounters(rocprofiler_record_profiler_t* record, const pending_signal_t& pending) {
rocmtools::metrics::GetCounterData(pending.profile, pending.context->results_list);
rocmtools::metrics::GetMetricsData(pending.context->results_map, pending.context->metrics_list);
@@ -260,6 +275,47 @@ void AddRecordCounters(rocprofiler_record_profiler_t* record, const pending_sign
record->counters_count = rocprofiler_record_counters_instances_count_t{counters_vec.size()};
}
void AddAttRecord(rocprofiler_record_att_tracer_t* record, hsa_agent_t gpu_agent,
att_pending_signal_t& pending) {
att_trace_callback_data_t data;
hsa_ven_amd_aqlprofile_iterate_data(pending.profile, attTraceDataCallback, &data);
// Get CPU and GPU memory pools
Packet::att_memory_pools_t* att_mem_pools = Packet::GetAttMemPools(gpu_agent);
// Allocate memory for shader_engine_data
record->shader_engine_data = static_cast<rocprofiler_record_se_att_data_t*>(
malloc(data.size() * sizeof(rocprofiler_record_se_att_data_t)));
att_trace_callback_data_t::iterator trace_data_it;
uint32_t se_index = 0;
// iterate over the trace data collected from each shader engine
for (trace_data_it = data.begin(); trace_data_it != data.end(); trace_data_it++) {
const void* data_ptr = trace_data_it->trace_data.ptr;
const uint32_t data_size = trace_data_it->trace_data.size;
// fprintf(arg->file, " SE(%u) size(%u)\n", data.sample_id, data_size);
void* buffer = NULL;
if (data_size != 0) {
// Allocate buffer on CPU to copy out trace data
buffer = Packet::AllocateSysMemory(gpu_agent, data_size, &att_mem_pools->cpu_mem_pool);
if (buffer == NULL) fatal("Trace data buffer allocation failed");
auto status =
rocmtools::hsa_support::GetCoreApiTable().hsa_memory_copy_fn(buffer, data_ptr, data_size);
if (status != HSA_STATUS_SUCCESS) fatal("Trace data memcopy to host failed");
record->shader_engine_data[se_index].buffer_ptr = buffer;
record->shader_engine_data[se_index].buffer_size = data_size;
++se_index;
// TODO: clear output buffers after copying
}
}
record->shader_engine_data_count = data.size();
}
// static const size_t MEM_PAGE_BYTES = 0x1000;
// static const size_t MEM_PAGE_MASK = MEM_PAGE_BYTES - 1;
// static std::mutex begin_signal_lock;
@@ -418,6 +474,67 @@ bool AsyncSignalHandler(hsa_signal_value_t signal_value, void* data) {
return false;
}
bool AsyncSignalHandlerATT(hsa_signal_value_t /* signal */, void* data) {
// TODO: finish implementation to iterate trace data and add it to rocmtools record
// and generic buffer
auto queue_info_session = static_cast<queue_info_session_t*>(data);
if (!queue_info_session || !GetROCMToolObj() ||
!GetROCMToolObj()->GetSession(queue_info_session->session_id) ||
!GetROCMToolObj()->GetSession(queue_info_session->session_id)->GetAttTracer())
return true;
rocmtools::Session* session = GetROCMToolObj()->GetSession(queue_info_session->session_id);
rocmtools::att::AttTracer* att_tracer = session->GetAttTracer();
std::vector<att_pending_signal_t>& pending_signals =
const_cast<std::vector<att_pending_signal_t>&>(
att_tracer->GetPendingSignals(queue_info_session->writer_id));
if (!pending_signals.empty()) {
for (auto it = pending_signals.begin(); it != pending_signals.end();
it = pending_signals.erase(it)) {
auto& pending = *it;
std::lock_guard<std::mutex> lock(session->GetSessionLock());
if (hsa_support::GetCoreApiTable().hsa_signal_load_relaxed_fn(pending.signal)) return true;
rocprofiler_record_att_tracer_t record{};
record.kernel_id = rocprofiler_kernel_id_t{pending.kernel_descriptor};
record.gpu_id = rocprofiler_agent_id_t{
(uint64_t)hsa_support::GetAgentInfo(queue_info_session->agent.handle).getIndex()};
record.kernel_properties = pending.kernel_properties;
record.thread_id = rocprofiler_thread_id_t{pending.thread_id};
record.queue_idx = rocprofiler_queue_index_t{pending.queue_index};
record.queue_id = rocprofiler_queue_id_t{queue_info_session->queue_id};
if (/*pending.counters_count > 0 && */ pending.profile) {
AddAttRecord(&record, queue_info_session->agent, pending);
}
record.header = {ROCPROFILER_ATT_TRACER_RECORD,
rocprofiler_record_id_t{GetROCMToolObj()->GetUniqueRecordId()}};
if (pending.session_id.handle == 0) {
pending.session_id = GetROCMToolObj()->GetCurrentSessionId();
}
if (session->FindBuffer(pending.buffer_id)) {
Memory::GenericBuffer* buffer = session->GetBuffer(pending.buffer_id);
record.header.id = rocprofiler_record_id_t{GetROCMToolObj()->GetUniqueRecordId()};
buffer->AddRecord(record);
}
hsa_status_t status = rocmtools::hsa_support::GetAmdExtTable().hsa_amd_memory_pool_free_fn(
(pending.profile->output_buffer.ptr));
if (status != HSA_STATUS_SUCCESS) {
printf("Error: Couldn't free output buffer memory\n");
}
status = rocmtools::hsa_support::GetAmdExtTable().hsa_amd_memory_pool_free_fn(
(pending.profile->command_buffer.ptr));
if (status != HSA_STATUS_SUCCESS) {
printf("Error: Couldn't free command buffer memory\n");
}
delete pending.profile;
}
}
delete queue_info_session;
return false;
}
void CreateBarrierPacket(const hsa_signal_t& packet_completion_signal,
std::vector<Packet::packet_t>* transformed_packets) {
hsa_barrier_and_packet_t barrier{0};
@@ -439,6 +556,12 @@ void SignalAsyncHandler(const hsa_signal_t& signal, void* data) {
if (status != HSA_STATUS_SUCCESS) fatal("hsa_amd_signal_async_handler failed");
}
void signalAsyncHandlerATT(const hsa_signal_t& signal, void* data) {
hsa_status_t status = hsa_support::GetAmdExtTable().hsa_amd_signal_async_handler_fn(
signal, HSA_SIGNAL_CONDITION_EQ, 0, AsyncSignalHandlerATT, data);
if (status != HSA_STATUS_SUCCESS) fatal("hsa_amd_signal_async_handler failed");
}
void CreateSignal(uint32_t attribute, hsa_signal_t* signal) {
hsa_status_t status =
hsa_support::GetAmdExtTable().hsa_amd_signal_create_fn(1, 0, nullptr, attribute, signal);
@@ -459,6 +582,7 @@ template <typename Integral> constexpr Integral bit_extract(Integral x, int firs
return (x >> first) & bit_mask<Integral>(0, last - first);
}
static int KernelInterceptCount = 0;
std::atomic<uint32_t> WRITER_ID{0};
/**
* @brief This function is a queue write interceptor. It intercepts the
@@ -487,9 +611,12 @@ void WriteInterceptor(const void* packets, uint64_t pkt_count, uint64_t user_pkt
bool is_counter_collection_mode = false;
bool is_timestamp_collection_mode = false;
bool is_att_collection_mode = false;
bool is_pc_sampling_collection_mode = false;
std::vector<rocprofiler_att_parameter_t> att_parameters_data;
uint32_t replay_mode_count = 0;
std::vector<std::string> kernel_profile_names;
std::vector<std::string> att_counters_names;
rocmtools::Session* session = nullptr;
@@ -509,6 +636,17 @@ void WriteInterceptor(const void* packets, uint64_t pkt_count, uint64_t user_pkt
session->GetFilterIdWithKind(ROCPROFILER_DISPATCH_TIMESTAMPS_COLLECTION);
rocmtools::Filter* filter = session->GetFilter(filter_id);
buffer_id = filter->GetBufferId();
} else if (session && session->FindFilterWithKind(ROCPROFILER_ATT_TRACE_COLLECTION)) {
rocprofiler_filter_id_t filter_id =
session->GetFilterIdWithKind(ROCPROFILER_ATT_TRACE_COLLECTION);
rocmtools::Filter* filter = session->GetFilter(filter_id);
att_parameters_data = filter->GetAttParametersData();
is_att_collection_mode = true;
buffer_id = session->GetFilter(session->GetFilterIdWithKind(ROCPROFILER_ATT_TRACE_COLLECTION))
->GetBufferId();
att_counters_names = filter->GetCounterData();
kernel_profile_names = std::get<std::vector<std::string>>(filter->GetProperty(ROCPROFILER_FILTER_KERNEL_NAMES));
} else if (session && session->FindFilterWithKind(ROCPROFILER_PC_SAMPLING_COLLECTION)) {
is_pc_sampling_collection_mode = true;
}
@@ -527,10 +665,12 @@ void WriteInterceptor(const void* packets, uint64_t pkt_count, uint64_t user_pkt
std::vector<std::pair<rocmtools::profiling_context_t*, hsa_ven_amd_aqlprofile_profile_t*>>*
profiles = nullptr;
// Searching accross all the packets given during this write
for (size_t i = 0; i < pkt_count; ++i) {
auto& original_packet = static_cast<const hsa_barrier_and_packet_t*>(packets)[i];
// +Skip kernel dispatch IDs not wanted
// Skip packets other than kernel dispatch packets.
if (bit_extract(original_packet.header, HSA_PACKET_HEADER_TYPE,
HSA_PACKET_HEADER_TYPE + HSA_PACKET_HEADER_WIDTH_TYPE - 1) !=
@@ -659,6 +799,185 @@ void WriteInterceptor(const void* packets, uint64_t pkt_count, uint64_t user_pkt
}
/* Write the transformed packets to the hardware queue. */
writer(&transformed_packets[0], transformed_packets.size());
} else if (session_id.handle > 0 && pkt_count > 0 && is_att_collection_mode && session) {
// att start
// Getting Queue Data and Information
auto& queue_info = *static_cast<Queue*>(data);
std::lock_guard<std::mutex> lk(queue_info.qw_mutex);
Agent::AgentInfo* agentInfo = &(hsa_support::GetAgentInfo(queue_info.GetGPUAgent().handle));
if (agentInfo->getName().substr(0, 4) != "gfx9") {
printf("ATT collection is only supported for gfx9 at the moment!\n");
exit(1);
}
// Preparing att Packets
Packet::packet_t start_packet{};
Packet::packet_t stop_packet{};
hsa_ven_amd_aqlprofile_profile_t* profile = nullptr;
if (att_parameters_data.size() > 0 && is_att_collection_mode) {
// TODO sauverma: convert att_parameters_data to pass to generateattPackets
std::vector<hsa_ven_amd_aqlprofile_parameter_t> att_params;
int num_att_counters = 0;
for (rocprofiler_att_parameter_t& param : att_parameters_data) {
att_params.push_back({
static_cast<hsa_ven_amd_aqlprofile_parameter_name_t>(int(param.parameter_name)),
param.value
});
num_att_counters += param.parameter_name == ROCPROFILER_ATT_PERFCOUNTER;
}
if (att_counters_names.size() > 0) {
MetricsDict* metrics_dict_ = MetricsDict::Create(agentInfo);
for (const std::string& counter_name : att_counters_names) {
const Metric* metric = metrics_dict_->Get(counter_name);
const BaseMetric* base = dynamic_cast<const BaseMetric*>(metric);
if (!base) {
printf("Invalid base metric value: %s\n", counter_name.c_str());
exit(1);
}
std::vector<const counter_t*> counters;
base->GetCounters(counters);
hsa_ven_amd_aqlprofile_event_t event = counters[0]->event;
if (event.block_name != HSA_VEN_AMD_AQLPROFILE_BLOCK_NAME_SQ) {
printf("Only events from the SQ block can be selected for ATT.");
exit(1);
}
att_params.push_back({
static_cast<hsa_ven_amd_aqlprofile_parameter_name_t>(int(ROCPROFILER_ATT_PERFCOUNTER)),
event.counter_id | (event.counter_id ? (0xF<<24) : 0)
});
num_att_counters += 1;
}
hsa_ven_amd_aqlprofile_parameter_t zero_perf = {
static_cast<hsa_ven_amd_aqlprofile_parameter_name_t>(int(ROCPROFILER_ATT_PERFCOUNTER)), 0};
// Fill other perfcounters with 0's
for(; num_att_counters<16; num_att_counters++) att_params.push_back(zero_perf);
}
// Get the PM4 Packets using packets_generator
profile = Packet::GenerateATTPackets(queue_info.GetCPUAgent(), queue_info.GetGPUAgent(),
att_params, &start_packet, &stop_packet);
}
// Searching across all the packets given during this write
for (size_t i = 0; i < pkt_count; ++i) {
auto& original_packet = static_cast<const hsa_barrier_and_packet_t*>(packets)[i];
// Skip packets other than kernel dispatch packets.
if (bit_extract(original_packet.header, HSA_PACKET_HEADER_TYPE,
HSA_PACKET_HEADER_TYPE + HSA_PACKET_HEADER_WIDTH_TYPE - 1) !=
HSA_PACKET_TYPE_KERNEL_DISPATCH) {
transformed_packets.emplace_back(packets_arr[i]);
continue;
}
auto& kdispatch = static_cast<const hsa_kernel_dispatch_packet_s*>(packets)[i];
uint64_t kernel_object = kdispatch.kernel_object;
bool b_profile_this_object = false;
// Try to match the mangled kernel name with given matches in input.txt
try {
std::lock_guard<std::mutex> lock(ksymbol_map_lock);
assert(ksymbols);
const std::string& kernel_name = ksymbols->at(kernel_object);
// We want to initiate att profiling only if a match exists
for(const std::string& kernel_matches : kernel_profile_names) {
if (kernel_name.find(kernel_matches) != std::string::npos) {
b_profile_this_object = true;
break;
}
}
if (!b_profile_this_object) printf("Skipping: %s\n", kernel_name.c_str());
} catch (...) {
printf("Warning: Unknown name for object %lu\n", kernel_object);
}
// If no match was found or intercept count > maximum desired profiles, skip this kernel.
if (!b_profile_this_object || KernelInterceptCount >= MAX_ATT_PROFILES) {
printf("Skipping: %lu\n", kernel_object);
transformed_packets.emplace_back(packets_arr[i]);
continue;
}
KernelInterceptCount += 1;
uint32_t writer_id = WRITER_ID.fetch_add(1, std::memory_order_release);
if (att_parameters_data.size() > 0 && is_att_collection_mode && profile) {
// Adding start packet and its barrier with a dummy signal
hsa_signal_t dummy_signal{};
dummy_signal.handle = 0;
start_packet.header = HSA_PACKET_TYPE_VENDOR_SPECIFIC << HSA_PACKET_HEADER_TYPE;
AddVendorSpecificPacket(&start_packet, &transformed_packets, dummy_signal);
CreateBarrierPacket(start_packet.completion_signal, &transformed_packets);
}
auto& packet = transformed_packets.emplace_back(packets_arr[i]);
auto& dispatch_packet = reinterpret_cast<hsa_kernel_dispatch_packet_t&>(packet);
CreateSignal(HSA_AMD_SIGNAL_AMD_GPU_ONLY, &packet.completion_signal);
// Adding the dispatch packet newly created signal to the pending signals
// list to be processed by the signal interrupt
rocprofiler_kernel_properties_t kernel_properties =
set_kernel_properties(dispatch_packet, queue_info.GetGPUAgent());
if (session && profile) {
session->GetAttTracer()->AddPendingSignals(
writer_id, dispatch_packet.kernel_object, dispatch_packet.completion_signal, session_id,
buffer_id, profile, kernel_properties, (uint32_t)syscall(__NR_gettid), user_pkt_index);
} else {
session->GetAttTracer()->AddPendingSignals(
writer_id, dispatch_packet.kernel_object, dispatch_packet.completion_signal, session_id,
buffer_id, nullptr, kernel_properties, (uint32_t)syscall(__NR_gettid), user_pkt_index);
}
// Make a copy of the original packet, adding its signal to a barrier packet
if (original_packet.completion_signal.handle) {
hsa_barrier_and_packet_t barrier{0};
barrier.header = HSA_PACKET_TYPE_BARRIER_AND << HSA_PACKET_HEADER_TYPE;
Packet::packet_t* __attribute__((__may_alias__)) pkt =
(reinterpret_cast<Packet::packet_t*>(&barrier));
transformed_packets.emplace_back(*pkt).completion_signal =
original_packet.completion_signal;
}
// Adding a barrier packet with the original packet's completion signal.
hsa_signal_t interrupt_signal;
CreateSignal(0, &interrupt_signal);
// Adding Stop PM4 Packets
if (att_parameters_data.size() > 0 && is_att_collection_mode && profile) {
stop_packet.header = HSA_PACKET_TYPE_VENDOR_SPECIFIC << HSA_PACKET_HEADER_TYPE;
AddVendorSpecificPacket(&stop_packet, &transformed_packets, interrupt_signal);
// Added Interrupt Signal with barrier and provided handler for it
CreateBarrierPacket(interrupt_signal, &transformed_packets);
} else {
hsa_barrier_and_packet_t barrier{0};
barrier.header = HSA_PACKET_TYPE_BARRIER_AND << HSA_PACKET_HEADER_TYPE;
barrier.completion_signal = interrupt_signal;
Packet::packet_t* __attribute__((__may_alias__)) pkt =
(reinterpret_cast<Packet::packet_t*>(&barrier));
transformed_packets.emplace_back(*pkt);
}
// Creating Async Handler to be called every time the interrupt signal is
// marked complete
signalAsyncHandlerATT(
interrupt_signal,
new queue_info_session_t{queue_info.GetGPUAgent(), session_id, queue_info.GetQueueID(),
writer_id, interrupt_signal});
}
/* Write the transformed packets to the hardware queue. */
writer(&transformed_packets[0], transformed_packets.size());
// ATT end
} else {
/* Write the original packets to the hardware queue if no profiling session
* is active */
+8 -1
Просмотреть файл
@@ -43,7 +43,8 @@ GenericBuffer::GenericBuffer(rocprofiler_session_id_t session_id, rocprofiler_bu
// pointer moves to the other buffer. Each buffer should be large enough to
// hold at least 2 activity records, as record pairs may be written when
// external correlation ids are used.
const size_t allocation_size = 2 * std::max(2 * sizeof(rocprofiler_record_header_t), buffer_size);
const size_t allocation_size =
2 * std::max(2 * sizeof(rocprofiler_record_header_t), buffer_size);
pool_begin_ = nullptr;
AllocateMemory(&pool_begin_, allocation_size);
assert(pool_begin_ != nullptr && "pool allocator failed");
@@ -213,6 +214,12 @@ bool GetNextRecord(const rocprofiler_record_header_t* record,
// break;
*next = reinterpret_cast<const rocprofiler_record_header_t*>(tracer_record + 1);
}
case ROCPROFILER_ATT_TRACER_RECORD: {
const rocprofiler_record_att_tracer_t* att_tracer_record =
reinterpret_cast<const rocprofiler_record_att_tracer_t*>(record);
*next = reinterpret_cast<const rocprofiler_record_header_t*>(att_tracer_record + 1);
break;
}
default:
const rocprofiler_record_tracer_t* tracer_record =
reinterpret_cast<const rocprofiler_record_tracer_t*>(record);
+57
Просмотреть файл
@@ -0,0 +1,57 @@
/* Copyright (c) 2022 Advanced Micro Devices, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */
#include "att.h"
#include <cassert>
namespace rocmtools {
namespace att {
AttTracer::AttTracer(rocprofiler_buffer_id_t buffer_id, rocprofiler_filter_id_t filter_id,
rocprofiler_session_id_t session_id)
: buffer_id_(buffer_id), filter_id_(filter_id), session_id_(session_id) {}
AttTracer::~AttTracer() {}
void AttTracer::AddPendingSignals(uint32_t writer_id, uint64_t kernel_object,
const hsa_signal_t& completion_signal,
rocprofiler_session_id_t session_id,
rocprofiler_buffer_id_t buffer_id,
hsa_ven_amd_aqlprofile_profile_t* profile,
rocprofiler_kernel_properties_t kernel_properties,
uint32_t thread_id, uint64_t queue_index) {
std::lock_guard<std::mutex> lock(sessions_pending_signals_lock_);
if (sessions_pending_signals_.find(writer_id) == sessions_pending_signals_.end())
sessions_pending_signals_.emplace(writer_id, std::vector<att_pending_signal_t>());
sessions_pending_signals_.at(writer_id).emplace_back(
att_pending_signal_t{kernel_object, completion_signal, session_id_, buffer_id, profile,
kernel_properties, thread_id, queue_index});
}
const std::vector<att_pending_signal_t>& AttTracer::GetPendingSignals(uint32_t writer_id) {
std::lock_guard<std::mutex> lock(sessions_pending_signals_lock_);
assert(sessions_pending_signals_.find(writer_id) != sessions_pending_signals_.end() &&
"writer_id is not found in the pending_signals");
return sessions_pending_signals_.at(writer_id);
}
} // namespace att
} // namespace rocmtools
+76
Просмотреть файл
@@ -0,0 +1,76 @@
/* Copyright (c) 2022 Advanced Micro Devices, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */
#ifndef SRC_CORE_SESSION_ATT_ATT_H_
#define SRC_CORE_SESSION_ATT_ATT_H_
#include <hsa/hsa_ven_amd_aqlprofile.h>
#include <map>
#include <mutex>
#include <string>
#include <vector>
#include "inc/rocprofiler.h"
namespace rocmtools {
typedef struct {
uint64_t kernel_descriptor;
hsa_signal_t signal;
rocprofiler_session_id_t session_id;
rocprofiler_buffer_id_t buffer_id;
hsa_ven_amd_aqlprofile_profile_t* profile;
rocprofiler_kernel_properties_t kernel_properties;
uint32_t thread_id;
uint64_t queue_index;
} att_pending_signal_t;
namespace att {
class AttTracer {
public:
AttTracer(rocprofiler_buffer_id_t buffer_id, rocprofiler_filter_id_t filter_id,
rocprofiler_session_id_t session_id);
~AttTracer();
void AddPendingSignals(uint32_t writer_id, uint64_t kernel_object,
const hsa_signal_t& completion_signal, rocprofiler_session_id_t session_id,
rocprofiler_buffer_id_t buffer_id, hsa_ven_amd_aqlprofile_profile_t* profile,
rocprofiler_kernel_properties_t kernel_properties, uint32_t thread_id,
uint64_t queue_index);
const std::vector<att_pending_signal_t>& GetPendingSignals(uint32_t writer_id);
private:
rocprofiler_buffer_id_t buffer_id_;
rocprofiler_filter_id_t filter_id_;
rocprofiler_session_id_t session_id_;
std::mutex sessions_pending_signals_lock_;
std::map<uint32_t, std::vector<att_pending_signal_t>> sessions_pending_signals_;
};
} // namespace att
} // namespace rocmtools
#endif // SRC_CORE_SESSION_ATT_ATT_H_
+38 -7
Просмотреть файл
@@ -35,12 +35,25 @@ Filter::Filter(rocprofiler_filter_id_t id, rocprofiler_filter_kind_t filter_kind
}
case ROCPROFILER_COUNTERS_COLLECTION: {
profiler_counter_names_.clear();
for (uint32_t j = 0; j < data_count; j++)
for (uint32_t j = 0; j < data_count; j++) {
profiler_counter_names_.emplace_back(filter_data.counters_names[j]);
}
break;
}
case ROCPROFILER_PC_SAMPLING_COLLECTION:
case ROCPROFILER_ATT_TRACE: {
case ROCPROFILER_PC_SAMPLING_COLLECTION:{
break;
}
case ROCPROFILER_ATT_TRACE_COLLECTION: {
att_parameters_.clear();
profiler_counter_names_.clear();
for (uint32_t j = 0; j < data_count; j++) {
if (filter_data.att_parameters[j].parameter_name != ROCPROFILER_ATT_PERFCOUNTER_NAME) {
att_parameters_.emplace_back(filter_data.att_parameters[j]);
} else {
profiler_counter_names_.emplace_back(filter_data.att_parameters[j].counter_name);
}
}
break;
}
case ROCPROFILER_SPM_COLLECTION: {
@@ -49,8 +62,9 @@ Filter::Filter(rocprofiler_filter_id_t id, rocprofiler_filter_kind_t filter_kind
}
case ROCPROFILER_API_TRACE: {
tracer_apis_.clear();
for (uint32_t j = 0; j < data_count; j++)
tracer_apis_.emplace_back(filter_data.trace_apis[j]);
for (uint32_t j = 0; j < data_count; j++){
tracer_apis_.emplace_back(filter_data.trace_apis[j]);
}
break;
}
default: {
@@ -73,7 +87,7 @@ rocprofiler_filter_kind_t Filter::GetKind() { return kind_; }
std::mutex counter_data_lock;
std::vector<std::string> Filter::GetCounterData() {
if (kind_ == ROCPROFILER_COUNTERS_COLLECTION) {
if (kind_ == ROCPROFILER_COUNTERS_COLLECTION || kind_ == ROCPROFILER_ATT_TRACE_COLLECTION) {
std::lock_guard<std::mutex> lock(counter_data_lock);
return profiler_counter_names_;
}
@@ -90,6 +104,16 @@ std::vector<rocprofiler_tracer_activity_domain_t> Filter::GetTraceData() {
"Error: ROCMtools filter specified is not supported for "
"profiler mode!\n");
}
std::vector<rocprofiler_att_parameter_t> Filter::GetAttParametersData() {
if (kind_ == ROCPROFILER_ATT_TRACE_COLLECTION) {
return att_parameters_;
}
fatal(
"Error: ROCMtools filter specified is not supported for "
"ATT tracing mode!\n");
}
rocprofiler_spm_parameter_t* Filter::GetSpmParameterData() {
if (kind_ == ROCPROFILER_SPM_COLLECTION) {
return spm_parameter_;
@@ -143,7 +167,8 @@ void Filter::SetProperty(rocprofiler_filter_property_t property) {
}
case ROCPROFILER_FILTER_KERNEL_NAMES: {
if (kind_ == ROCPROFILER_COUNTERS_COLLECTION ||
kind_ == ROCPROFILER_DISPATCH_TIMESTAMPS_COLLECTION) {
kind_ == ROCPROFILER_DISPATCH_TIMESTAMPS_COLLECTION ||
kind_ == ROCPROFILER_ATT_TRACE_COLLECTION) {
kernel_names_.clear();
for (uint32_t j = 0; j < property.data_count; j++)
kernel_names_.emplace_back(property.name_regex[j]);
@@ -166,23 +191,29 @@ std::variant<std::vector<std::string>, uint32_t*> Filter::GetProperty(
switch (kind) {
case ROCPROFILER_FILTER_GPU_NAME: {
property = agent_names_;
break;
}
case ROCPROFILER_FILTER_RANGE: {
property = static_cast<uint32_t*>(dispatch_range_);
break;
}
case ROCPROFILER_FILTER_KERNEL_NAMES: {
property = kernel_names_;
break;
}
case ROCPROFILER_FILTER_HSA_TRACER_API_FUNCTIONS: {
property = hsa_tracer_api_calls_;
break;
}
case ROCPROFILER_FILTER_HIP_TRACER_API_FUNCTIONS: {
property = hip_tracer_api_calls_;
break;
}
default:
fatal(
"Error: ROCMtools filter specified is not supported for the given "
"kind!");
break;
}
return property;
}
+2 -1
Просмотреть файл
@@ -47,7 +47,7 @@ class Filter {
std::vector<std::string> GetCounterData();
std::vector<rocprofiler_tracer_activity_domain_t> GetTraceData();
std::vector<rocprofiler_att_parameter_t> GetAttParametersData();
void SetCallback(rocprofiler_sync_callback_t& callback);
rocprofiler_sync_callback_t& GetCallback();
@@ -71,6 +71,7 @@ class Filter {
std::vector<std::string> profiler_counter_names_; // Counter Names to collect
std::vector<rocprofiler_tracer_activity_domain_t> tracer_apis_; // ROCTX/HIP/HSA API
rocprofiler_spm_parameter_t* spm_parameter_; // spm parameter
std::vector<rocprofiler_att_parameter_t> att_parameters_; // ATT Parameters
rocprofiler_sync_callback_t callback_;
};
+12
Просмотреть файл
@@ -54,6 +54,10 @@ Session::~Session() {
// delete tracer_;
// tracer_started_.exchange(false, std::memory_order_release);
// }
if (att_tracer_started_.load(std::memory_order_release)) {
delete att_tracer_;
att_tracer_started_.exchange(false, std::memory_order_release);
}
// {
// std::lock_guard<std::mutex> lock(filters_lock_);
// buffers_.clear();
@@ -99,6 +103,13 @@ void Session::Start() {
GetFilter(GetFilterIdWithKind(ROCPROFILER_COUNTERS_COLLECTION))->GetId(), session_id_);
profiler_started_.exchange(true, std::memory_order_release);
}
if (FindFilterWithKind(ROCPROFILER_ATT_TRACE_COLLECTION)) {
if (att_tracer_started_.load(std::memory_order_release)) delete att_tracer_;
att_tracer_ = new att::AttTracer(
GetFilter(GetFilterIdWithKind(ROCPROFILER_ATT_TRACE_COLLECTION))->GetBufferId(),
GetFilter(GetFilterIdWithKind(ROCPROFILER_ATT_TRACE_COLLECTION))->GetId(), session_id_);
att_tracer_started_.exchange(true, std::memory_order_release);
}
if (FindFilterWithKind(ROCPROFILER_SPM_COLLECTION)) {
if (spm_started_.load(std::memory_order_release)) delete spmcounter_;
@@ -176,6 +187,7 @@ rocprofiler_session_id_t Session::GetId() { return session_id_; }
bool Session::IsActive() { return is_active_; }
profiler::Profiler* Session::GetProfiler() { return profiler_; }
att::AttTracer* Session::GetAttTracer() { return att_tracer_; }
tracer::Tracer* Session::GetTracer() { return tracer_; }
spm::SpmCounters* Session::GetSpmCounter() { return spmcounter_; }
pc_sampler::PCSampler* Session::GetPCSampler() { return pc_sampler_; }
+4
Просмотреть файл
@@ -37,6 +37,7 @@
#include "src/core/session/filter.h"
#include "profiler/profiler.h"
#include "tracer/tracer.h"
#include "att/att.h"
#include "spm/spm.h"
#include "src/pcsampler/session/pc_sampler.h"
@@ -58,6 +59,7 @@ class Session {
profiler::Profiler* GetProfiler();
tracer::Tracer* GetTracer();
att::AttTracer* GetAttTracer();
spm::SpmCounters* GetSpmCounter();
pc_sampler::PCSampler* GetPCSampler();
@@ -104,6 +106,8 @@ class Session {
std::atomic<bool> profiler_started_{false};
std::atomic<bool> tracer_started_{false};
std::atomic<bool> att_tracer_started_{false};
att::AttTracer* att_tracer_;
std::atomic<bool> spm_started_{false};
profiler::Profiler* profiler_;
+168 -4
Просмотреть файл
@@ -172,6 +172,134 @@ std::vector<std::string> GetCounterNames() {
return counters;
}
typedef std::tuple<
std::vector<std::pair<rocprofiler_att_parameter_name_t, uint32_t>>,
std::vector<std::string>, std::vector<std::string>
> att_parsed_input_t;
att_parsed_input_t GetATTParams() {
std::vector<std::pair<rocprofiler_att_parameter_name_t, uint32_t>> parameters;
std::vector<std::string> kernel_names;
std::vector<std::string> counters_names;
const char* path = getenv("COUNTERS_PATH");
// List of parameters the user can set. Maxvalue is unused.
std::unordered_map<std::string, rocprofiler_att_parameter_name_t> ATT_PARAM_NAMES{};
ATT_PARAM_NAMES["att: TARGET_CU"] = ROCPROFILER_ATT_COMPUTE_UNIT_TARGET;
ATT_PARAM_NAMES["SIMD_MASK"] = ROCPROFILER_ATT_MAXVALUE;
ATT_PARAM_NAMES["PERFCOUNTER_ID"] = ROCPROFILER_ATT_PERFCOUNTER;
ATT_PARAM_NAMES["PERFCOUNTER"] = ROCPROFILER_ATT_PERFCOUNTER_NAME;
ATT_PARAM_NAMES["PERFCOUNTERS_COL_PERIOD"] = ROCPROFILER_ATT_MAXVALUE;
ATT_PARAM_NAMES["KERNEL"] = ROCPROFILER_ATT_MAXVALUE;
ATT_PARAM_NAMES["REDUCED_MEMORY"] = ROCPROFILER_ATT_MAXVALUE;
/*
ATT_PARAM_NAMES["ATT_MASK"] = ROCMTOOLS_ATT_MASK;
ATT_PARAM_NAMES["TOKEN_MASK"] = ROCMTOOLS_ATT_TOKEN_MASK;
ATT_PARAM_NAMES["TOKEN_MASK2"] = ROCMTOOLS_ATT_TOKEN_MASK2;
ATT_PARAM_NAMES["SE_MASK"] = ROCMTOOLS_ATT_SE_MASK;
ATT_PARAM_NAMES["PERF_MASK"] = ROCMTOOLS_ATT_PERF_MASK;
ATT_PARAM_NAMES["PERF_CTRL"] = ROCMTOOLS_ATT_PERF_CTRL;
*/
// Default values used for token generation.
std::unordered_map<std::string, uint32_t> default_params = {
{"ATT_MASK", 0x3F01},
{"TOKEN_MASK", 0x344B},
{"TOKEN_MASK2", 0x3FFFF}
};
bool started_att_counters = false;
if (!path) return {parameters, kernel_names, counters_names};
std::string line;
std::ifstream trace_file(path);
if (!trace_file.is_open()) {
std::cout << "Unable to open att trace file." << std::endl;
return {parameters, kernel_names, counters_names};
}
while (getline(trace_file, line)) {
if (line.find("//") != std::string::npos)
line = line.substr(0, line.find("//")); // Remove comments
auto pos = line.find('=');
if (pos == std::string::npos)
continue;
std::string param_name = line.substr(0, pos);
uint32_t param_value;
if (param_name == "att: TARGET_CU") started_att_counters = true;
if (!started_att_counters) continue;
if (param_name == "KERNEL") {
kernel_names.push_back(line.substr(pos+1));
continue;
} else if (param_name == "PERFCOUNTER") {
counters_names.push_back(line.substr(pos+1));
continue;
} else { // param_value is a number
try {
auto hexa_pos = line.find("0x", pos); // Is it hex?
if (hexa_pos != std::string::npos)
param_value = stoi(line.substr(hexa_pos+2), 0, 16); // hexadecimal
else
param_value = stoi(line.substr(pos+1), 0, 10); // decimal
} catch(...) {
printf("Error: Invalid parameter value %s - (%s)\n",
line.substr(pos+1, line.size()).c_str(), line.c_str());
exit(1);
}
}
if (param_name == "PERFCOUNTERS_COL_PERIOD") {
default_params["TOKEN_MASK"] |= 0x4000;
param_value = ((param_value & 0x1F) << 8) | 0x007F;
parameters.push_back(std::make_pair(ROCPROFILER_ATT_PERF_CTRL, param_value));
continue;
} else if (param_name == "SIMD_MASK") {
default_params["ATT_MASK"] &= ~0xF00;
default_params["ATT_MASK"] |= (param_value<<8) & 0xF00;
continue;
} else if (param_name == "att: TARGET_CU") {
default_params["ATT_MASK"] &= ~0xF;
default_params["ATT_MASK"] |= param_value & 0xF;
} else if (param_name == "PERFCOUNTER_ID") {
param_value = param_value | (param_value ? (0xF<<24) : 0);
} else if (param_name == "REDUCED_MEMORY") {
default_params["TOKEN_MASK2"] = 0;
continue;
}
if (ATT_PARAM_NAMES.find(param_name) != ATT_PARAM_NAMES.end()) {
parameters.push_back(std::make_pair(ATT_PARAM_NAMES[param_name], param_value));
try { default_params.erase(param_name); } catch(...) {};
} else {
printf("Error: Invalid parameter name: %s - (%s)\nList of available params:\n",
param_name.c_str(), line.c_str());
for (auto& name : ATT_PARAM_NAMES) printf("%s\n", name.first.c_str());
}
}
trace_file.close();
if (!started_att_counters) return {parameters, kernel_names, counters_names};
ATT_PARAM_NAMES["ATT_MASK"] = ROCPROFILER_ATT_MASK;
ATT_PARAM_NAMES["TOKEN_MASK"] = ROCPROFILER_ATT_TOKEN_MASK;
ATT_PARAM_NAMES["TOKEN_MASK2"] = ROCPROFILER_ATT_TOKEN_MASK2;
for (auto& param : default_params)
parameters.push_back(std::make_pair(ATT_PARAM_NAMES[param.first], param.second));
// If no kernel names were provided, collect them all.
// Empty string always returns true for "str.find()".
if (kernel_names.size() == 0) kernel_names.push_back("");
return {parameters, kernel_names, counters_names};
}
void finish() {
if (amd_sys_handler.load(std::memory_order_release)) {
amd_sys_handler.exchange(false, std::memory_order_release);
@@ -335,19 +463,34 @@ ROCPROFILER_EXPORT bool OnLoad(HsaApiTable* table, uint64_t runtime_version,
std::vector<const char*> counters_;
if (counters.size() > 0) {
printf("ROCMTools: Collecting the following counters:\n");
printf("ROCProfilerV2: Collecting the following counters:\n");
for (size_t i = 0; i < counters.size(); i++) {
counters_.emplace_back(counters.at(i).c_str());
printf("- %s\n", counters_.back());
}
}
// ATT Parameters
std::vector<rocprofiler_att_parameter_t> parameters;
std::vector<std::pair<rocprofiler_att_parameter_name_t, uint32_t>> params;
std::vector<std::string> kernel_names;
std::vector<std::string> att_counters_names;
std::tie(params, kernel_names, att_counters_names) = GetATTParams();
for (auto& kv_pair : params)
parameters.emplace_back(rocprofiler_att_parameter_t{kv_pair.first, kv_pair.second});
for (std::string& name : att_counters_names) {
rocprofiler_att_parameter_t param;
param.parameter_name = ROCPROFILER_ATT_PERFCOUNTER_NAME;
param.counter_name = name.c_str();
parameters.emplace_back(param);
}
CHECK_ROCMTOOLS(rocprofiler_create_session(ROCPROFILER_KERNEL_REPLAY_MODE, &session_id));
bool want_pc_sampling = getenv("ROCPROFILER_PC_SAMPLING");
std::vector<rocprofiler_filter_kind_t> filters_requested;
if ((counters.size() == 0 && (apis_requested.size() == 0 || getenv("ROCPROFILER_KERNEL_TRACE")))
if (((counters.size() == 0 && parameters.size() == 0) && (apis_requested.size() == 0 || getenv("ROCPROFILER_KERNEL_TRACE")))
|| want_pc_sampling /* PC sampling needs a profiler, even it's doing
nothing */)
filters_requested.emplace_back(ROCPROFILER_DISPATCH_TIMESTAMPS_COLLECTION);
@@ -356,6 +499,7 @@ ROCPROFILER_EXPORT bool OnLoad(HsaApiTable* table, uint64_t runtime_version,
}
if (counters.size() > 0) filters_requested.emplace_back(ROCPROFILER_COUNTERS_COLLECTION);
if (apis_requested.size() > 0) filters_requested.emplace_back(ROCPROFILER_API_TRACE);
if (parameters.size() > 0) filters_requested.emplace_back(ROCPROFILER_ATT_TRACE_COLLECTION);
rocprofiler_buffer_id_t buffer_id;
CHECK_ROCMTOOLS(rocprofiler_create_buffer(
@@ -364,7 +508,7 @@ ROCPROFILER_EXPORT bool OnLoad(HsaApiTable* table, uint64_t runtime_version,
rocprofiler_session_id_t session_id, rocprofiler_buffer_id_t buffer_id) {
if (plugin) plugin->write_buffer_records(record, end_record, session_id, buffer_id);
},
0x9999, &buffer_id));
1<<20, &buffer_id));
buffer_ids.emplace_back(buffer_id);
rocprofiler_buffer_id_t buffer_id_1;
@@ -374,7 +518,7 @@ ROCPROFILER_EXPORT bool OnLoad(HsaApiTable* table, uint64_t runtime_version,
rocprofiler_session_id_t session_id, rocprofiler_buffer_id_t buffer_id_1) {
if (plugin) plugin->write_buffer_records(record, end_record, session_id, buffer_id_1);
},
0x9999, &buffer_id_1));
1<<20, &buffer_id_1));
buffer_ids.emplace_back(buffer_id_1);
for (rocprofiler_filter_kind_t filter_kind : filters_requested) {
@@ -412,6 +556,26 @@ ROCPROFILER_EXPORT bool OnLoad(HsaApiTable* table, uint64_t runtime_version,
filter_ids.emplace_back(filter_id);
break;
}
case ROCPROFILER_ATT_TRACE_COLLECTION: {
printf("Enabling ATT Tracing\n");
rocprofiler_filter_id_t filter_id;
std::vector<const char*> kernel_names_c;
for (auto& name : kernel_names) kernel_names_c.push_back(name.data());
rocprofiler_filter_property_t property = {};
property.kind = ROCPROFILER_FILTER_KERNEL_NAMES;
property.data_count = kernel_names_c.size();
property.name_regex = kernel_names_c.data();
CHECK_ROCMTOOLS(
rocprofiler_create_filter(session_id, ROCPROFILER_ATT_TRACE_COLLECTION,
rocprofiler_filter_data_t{.att_parameters = &parameters[0]},
parameters.size(), &filter_id, property));
CHECK_ROCMTOOLS(rocprofiler_set_filter_buffer(session_id, filter_id, buffer_id_1));
filter_ids.emplace_back(filter_id);
break;
}
case ROCPROFILER_PC_SAMPLING_COLLECTION: {
puts("Enabling PC sampling");
rocprofiler_filter_id_t filter_id;
+6
Просмотреть файл
@@ -185,6 +185,12 @@ target_link_libraries ( profiler_api_test ${ROCPROFILER_TARGET} ${ROCPROFILER_TA
target_include_directories(profiler_api_test PRIVATE ${TEST_DIR} ${ROOT_DIR} ${HSA_RUNTIME_INC_PATH} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/tests/featuretests/profiler)
add_dependencies(tests profiler_api_test)
set_source_files_properties(discretetests/api/att_test.cpp PROPERTIES HIP_SOURCE_PROPERTY_FORMAT 1)
hip_add_executable ( profiler_api_att_test discretetests/api/att_test.cpp utils/test_utils.cpp )
target_link_libraries ( profiler_api_att_test ${ROCPROFILER_TARGET} ${ROCPROFILER_TARGET} hsa-runtime64::hsa-runtime64 Threads::Threads dl stdc++fs )
target_include_directories(profiler_api_att_test PRIVATE ${TEST_DIR} ${ROOT_DIR} ${HSA_RUNTIME_INC_PATH} ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/tests/featuretests/profiler)
add_dependencies(tests profiler_api_att_test)
set_source_files_properties(discretetests/api/spm_test.cpp PROPERTIES HIP_SOURCE_PROPERTY_FORMAT 1)
hip_add_executable ( profiler_api_spm_test discretetests/api/spm_test.cpp utils/test_utils.cpp )
target_link_libraries ( profiler_api_spm_test ${ROCPROFILER_TARGET} ${ROCPROFILER_TARGET} hsa-runtime64::hsa-runtime64 Threads::Threads dl stdc++fs )
+259
Просмотреть файл
@@ -0,0 +1,259 @@
/******************************************************************************
Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*******************************************************************************/
#include <hip/hip_runtime.h>
#include <rocprofiler.h>
#include <cassert>
#include <functional>
#include <iostream>
#include <thread>
#include <vector>
#include "utils/test_utils.h"
#ifdef NDEBUG
#define HIP_ASSERT(x) x
#else
#define HIP_ASSERT(x) (assert((x)==hipSuccess))
#endif
#define WIDTH 1024
#define HEIGHT 1024
#define NUM (WIDTH*HEIGHT)
#define THREADS_PER_BLOCK_X 16
#define THREADS_PER_BLOCK_Y 16
#define THREADS_PER_BLOCK_Z 1
/** \mainpage ROC Profiler API Test
*
* \section introduction Introduction
*
* The goal of this test is to test ROCmTools APIs to collect ATT traces.
*
* A simple vectoradd_float kernel is launched and the trace results are printed
* as console output
*/
// function to check att tracing API status
auto CheckApi = [](rocprofiler_status_t status) {
if (status != ROCPROFILER_STATUS_SUCCESS) {
std::cout << "ROCmTools API Error" << std::endl;
}
assert(status == ROCPROFILER_STATUS_SUCCESS);
};
// callback function to dump att tracing data
void FlushCallback(const rocprofiler_record_header_t* record,
const rocprofiler_record_header_t* end_record, rocprofiler_session_id_t session_id,
rocprofiler_buffer_id_t buffer_id) {
while (record < end_record) {
if (!record) break;
else if (record->kind == ROCPROFILER_ATT_TRACER_RECORD){
const rocprofiler_record_att_tracer_t* att_tracer_record =
reinterpret_cast<const rocprofiler_record_att_tracer_t*>(record);
size_t name_length;
CheckApi(rocprofiler_query_kernel_info_size(ROCPROFILER_KERNEL_NAME, att_tracer_record->kernel_id,
&name_length));
const char* kernel_name_c = static_cast<const char*>(malloc(name_length * sizeof(char)));
CheckApi(rocprofiler_query_kernel_info(ROCPROFILER_KERNEL_NAME, att_tracer_record->kernel_id,
&kernel_name_c));
int gpu_index = att_tracer_record->gpu_id.handle;
printf(
"Kernel Info:\n\tGPU Index: %d\n\tKernel Name: %s\n",
gpu_index, kernel_name_c);
// Get the number of shader engine traces
int se_num = att_tracer_record->shader_engine_data_count;
// iterate over each shader engine att trace
for (int i = 0; i < se_num; i++){
printf("\n\n-------------- shader_engine %d --------------\n\n", i);
rocprofiler_record_se_att_data_t* se_att_trace = &att_tracer_record->shader_engine_data[i];
uint32_t size = se_att_trace->buffer_size;
const unsigned short* data_buffer_ptr = reinterpret_cast<const unsigned short*>(se_att_trace->buffer_ptr);
// Print the buffer in terms of shorts (16 bits)
for (uint32_t j = 0; j < (size / sizeof(short)); j++)
printf("%04x\n", data_buffer_ptr[j]);
}
}
CheckApi(rocprofiler_next_record(record, &record, session_id, buffer_id));
}
}
__global__ void
vectoradd_float(float* __restrict__ a, const float* __restrict__ b, const float* __restrict__ c, int width, int height)
{
int x = hipBlockDim_x * hipBlockIdx_x + hipThreadIdx_x;
int y = hipBlockDim_y * hipBlockIdx_y + hipThreadIdx_y;
int i = y * width + x;
if ( i < (width * height)) {
a[i] = b[i] + c[i];
}
}
int LaunchVectorAddKernel() {
float* hostA;
float* hostB;
float* hostC;
float* deviceA;
float* deviceB;
float* deviceC;
hipDeviceProp_t devProp;
hipGetDeviceProperties(&devProp, 0);
std::cout << " System minor " << devProp.minor << std::endl;
std::cout << " System major " << devProp.major << std::endl;
std::cout << " agent prop name " << devProp.name << std::endl;
std::cout << "hip Device prop succeeded " << std::endl ;
int i;
int errors;
hostA = (float*)malloc(NUM * sizeof(float));
hostB = (float*)malloc(NUM * sizeof(float));
hostC = (float*)malloc(NUM * sizeof(float));
// initialize the input data
for (i = 0; i < NUM; i++) {
hostB[i] = (float)i;
hostC[i] = (float)i*100.0f;
}
HIP_ASSERT(hipMalloc((void**)&deviceA, NUM * sizeof(float)));
HIP_ASSERT(hipMalloc((void**)&deviceB, NUM * sizeof(float)));
HIP_ASSERT(hipMalloc((void**)&deviceC, NUM * sizeof(float)));
HIP_ASSERT(hipMemcpy(deviceB, hostB, NUM*sizeof(float), hipMemcpyHostToDevice));
HIP_ASSERT(hipMemcpy(deviceC, hostC, NUM*sizeof(float), hipMemcpyHostToDevice));
hipLaunchKernelGGL(vectoradd_float,
dim3(WIDTH/THREADS_PER_BLOCK_X, HEIGHT/THREADS_PER_BLOCK_Y),
dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y),
0, 0,
deviceA ,deviceB ,deviceC ,WIDTH ,HEIGHT);
HIP_ASSERT(hipMemcpy(hostA, deviceA, NUM*sizeof(float), hipMemcpyDeviceToHost));
// verify the results
errors = 0;
for (i = 0; i < NUM; i++) {
if (hostA[i] != (hostB[i] + hostC[i])) {
errors++;
}
}
if (errors!=0) {
printf("FAILED: %d errors\n",errors);
} else {
printf ("PASSED!\n");
}
HIP_ASSERT(hipFree(deviceA));
HIP_ASSERT(hipFree(deviceB));
HIP_ASSERT(hipFree(deviceC));
free(hostA);
free(hostB);
free(hostC);
//hipResetDefaultAccelerator();
return errors;
}
int main(int argc, char** argv) {
// inititalize rocmtools
CheckApi(rocprofiler_initialize());
// Att trace collection parameters
rocprofiler_session_id_t session_id;
std::vector<rocprofiler_att_parameter_t> parameters;
parameters.emplace_back(rocprofiler_att_parameter_t{ROCPROFILER_ATT_COMPUTE_UNIT_TARGET, 0});
parameters.emplace_back(rocprofiler_att_parameter_t{ROCPROFILER_ATT_MASK, 0x0F00});
parameters.emplace_back(rocprofiler_att_parameter_t{ROCPROFILER_ATT_TOKEN_MASK, 0x344B});
parameters.emplace_back(rocprofiler_att_parameter_t{ROCPROFILER_ATT_TOKEN_MASK2, 0xFFFF});
// create a session
CheckApi(rocprofiler_create_session(ROCPROFILER_KERNEL_REPLAY_MODE, &session_id));
// create a buffer to hold att trace records for each kernel launch
rocprofiler_buffer_id_t buffer_id;
CheckApi(rocprofiler_create_buffer(session_id, FlushCallback, 0x9999, &buffer_id));
// create a filter for collecting att traces
rocprofiler_filter_id_t filter_id;
rocprofiler_filter_property_t property = {};
CheckApi(rocprofiler_create_filter(session_id, ROCPROFILER_ATT_TRACE_COLLECTION,
rocprofiler_filter_data_t{.att_parameters = &parameters[0]},
parameters.size(), &filter_id, property));
// set buffer for the filter
CheckApi(rocprofiler_set_filter_buffer(session_id, filter_id, buffer_id));
// activating att tracing session
CheckApi(rocprofiler_start_session(session_id));
// Launch a kernel
LaunchVectorAddKernel();
// deactivate att tracing session
CheckApi(rocprofiler_terminate_session(session_id));
// dump att tracing data
CheckApi(rocprofiler_flush_data(session_id, buffer_id));
// destroy session
CheckApi(rocprofiler_destroy_session(session_id));
// finalize att tracing by destroying rocmtool object
CheckApi(rocprofiler_finalize());
return 0;
}
+2 -1
Просмотреть файл
@@ -43,10 +43,11 @@ file(GLOB ROCPROFILER_SRC_API_FILES ${PROJECT_SOURCE_DIR}/src/api/*.cpp)
file(GLOB ROCPROFILER_SRC_PROFILER_FILES ${PROJECT_SOURCE_DIR}/src/core/session/profiler/profiler.cpp)
file(GLOB ROCPROFILER_TRACER_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/tracer/*.cpp)
file(GLOB ROCPROFILER_ROCTRACER_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/tracer/src/*.cpp)
file(GLOB ROCPROFILER_ATT_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/att/att.cpp)
file(GLOB ROCPROFILER_SRC_CLASS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rocmtool.cpp)
file(GLOB ROCPROFILER_SPM_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/spm/spm.cpp)
set(ROCPROFILER_SRC_FILES ${ROCPROFILER_SRC_API_FILES} ${ROCPROFILER_SRC_CLASS_FILES} ${ROCPROFILER_SRC_PROFILER_FILES})
set(ROCPROFILER_SRC_FILES ${ROCPROFILER_SRC_API_FILES} ${ROCPROFILER_SRC_CLASS_FILES} ${ROCPROFILER_SRC_PROFILER_FILES} ${ROCPROFILER_ATT_SRC_FILES})
set(CORE_HSA_DIR ${PROJECT_SOURCE_DIR}/src/core/hsa)
file(GLOB CORE_HSA_SRC_FILES ${CORE_HSA_DIR}/*.cpp)
+2 -1
Просмотреть файл
@@ -31,11 +31,12 @@ file(GLOB CORE_COUNTERS_SRC_FILES ${PROJECT_BINARY_DIR}/src/api/*_counter.cpp)
file(GLOB ROCPROFILER_SRC_PROFILER_FILES ${PROJECT_SOURCE_DIR}/src/core/session/profiler/profiler.cpp)
file(GLOB ROCPROFILER_TRACER_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/tracer/*.cpp)
file(GLOB ROCPROFILER_ROCTRACER_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/tracer/src/*.cpp)
file(GLOB ROCPROFILER_ATT_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/att/att.cpp)
file(GLOB ROCPROFILER_SRC_CLASS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rocmtool.cpp)
file(GLOB ROCPROFILER_SPM_SRC_FILES ${PROJECT_SOURCE_DIR}/src/core/session/spm/spm.cpp)
file(GLOB ROCPROFILER_SRC_API_FILES ${PROJECT_SOURCE_DIR}/src/api/*.cpp)
set(ROCPROFILER_SRC_FILES ${ROCPROFILER_SRC_API_FILES} ${ROCPROFILER_SRC_CLASS_FILES} ${ROCPROFILER_SRC_PROFILER_FILES})
set(ROCPROFILER_SRC_FILES ${ROCPROFILER_SRC_API_FILES} ${ROCPROFILER_SRC_CLASS_FILES} ${ROCPROFILER_SRC_PROFILER_FILES} ${ROCPROFILER_ATT_SRC_FILES})
set(CORE_HSA_DIR ${PROJECT_SOURCE_DIR}/src/core/hsa)
file(GLOB CORE_HSA_SRC_FILES ${CORE_HSA_DIR}/*.cpp)