Shared Library Constructor (rocprofv3 deadlock fix) (#599)

* Moved tests/apps to tests/bin

* Renamed cmake project in tests/bin

* Update samples

- Use ROCPROFILER_DEFAULT_FAIL_REGEX
- tweaks to stdout messages

* Update tests

- Use ROCPROFILER_DEFAULT_FAIL_REGEX

* Add tests/lib

- libraries with HIP code

* Update PTL submodule

- remove atexit delete of thread_id_map

* Update cmake/rocprofiler_options.cmake

- Set ROCPROFILER_DEFAULT_FAIL_REGEX

* Update common lib: env + logging

- improved customization of logging settings
- default to disabling logging to files
- install failure handler for rocprofv3
- set_env support in environment.*

* Add lib/rocprofiler-sdk/shared_library.cpp

- shared library constructor

* Update lib/rocprofiler-sdk-tool/tool.cpp

- destructor thread safety
- convert callback_name_info and buffered_name_info to pointers
- install failure handler for logging

* Add tests/bin/hip-in-libraries

- hip-in-libraries is an exe which uses two shared libraries where each shared library contains HIP kernels
  - used for testing deadlocking within __hipRegisterFatBinary

* Update bin/rocprofv3

- reorganized the env variables
- use exec to launch command
- set ROCPROFILER_LIBRARY_CTOR=1

* Add tests/rocprofv3/tracing-hip-in-libraries

- uses hip-in-libraries exe for exe which uses shared libraries to launch HIP kernels

* Update bin/rocprofv3

- fix counter collection (no exec)

* Update lib/rocprofiler-sdk-tool/tool.cpp

- replace "Kernel-Name" with "Kernel_Name"

* Update lib/rocprofiler-sdk/registration.cpp

Use RTLD_LOCAL instead of RTLD_GLOBAL for env libraries

* Update tests/rocprofv3

- replace "Kernel-Name" with "Kernel_Name"

* Update tests

- vector-ops (bin) stream syncs + runs with 4 queues per device
- improve counter-collection/input1 validation
- rocprofv3/tracing-hip-in-libraries does not do sys-trace
- improved validation script for tracing-hip-in-libraries
- updated dispatch_callback in json-tool.cpp following reworking of prototypes for counter collection

* Update samples/counter_collection

- updated dispatch_callback(s) and record_callback(s) following reworking of prototypes

* Update bin/rocprofv3

- reorganized help menu
- added options for sub-HSA tables
- added --hip-runtime-trace
- changed --hip-trace to include --hip-compiler-trace

* Update lib/rocprofiler-sdk-tool

- improved kernel filtering
- removed arch_vgpr, accum_vgpr, sgpr code (in rocprofiler-sdk)
- fixed issue with counter-collection w/o tracing
- added support for fine grained HSA API tracing
- removed directly linking to HSA-runtime

* Update lib/rocprofiler-sdk/agent.cpp

- rocp_agents != hsa_agents is non-fatal when ROCPROFILER_BUILD_CI=OFF (CMake option)

* GPR (vector and scalar) info in kernel symbol data

- rocprofiler_callback_tracing_code_object_kernel_symbol_register_data_t contains general purpose register info

* Header include order fix

- Include repo headers first
- Third party library headers next
- standard library headers last

* Update dispatch profiling public API

- introduce rocprofiler_profile_counting_dispatch_data_t
- change signature of rocprofiler_profile_counting_dispatch_callback_t and rocprofiler_profile_counting_record_callback_t
- provide rocprofiler_user_data_t pointer in dispatch callback
- provide rocprofiler_user_data_t value (from dispatch cb) in record callback

* Update tests/bin/CMakeLists.txt

- fix add_subdirectory(hip-in-libraries) order

* Update VERSION

- bump to 0.2.0 in prep for AFAR
Этот коммит содержится в:
Jonathan R. Madsen
2024-03-07 22:21:26 -06:00
коммит произвёл GitHub
родитель 665c546e65
Коммит 7b6d3c70bd
85 изменённых файлов: 2497 добавлений и 856 удалений
+4 -1
Просмотреть файл
@@ -40,8 +40,11 @@ add_subdirectory(common)
# tool libraries used for data collection during integration tests
add_subdirectory(tools)
# libraries used by integration test applications
add_subdirectory(lib)
# applications used by integration tests
add_subdirectory(apps)
add_subdirectory(bin)
# validation tests
add_subdirectory(kernel-tracing)
+3 -2
Просмотреть файл
@@ -29,7 +29,8 @@ set(async-copy-tracing-env
set_tests_properties(
test-async-copy-tracing-execute
PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT
"${async-copy-tracing-env}" FAIL_REGULAR_EXPRESSION "threw an exception")
"${async-copy-tracing-env}" FAIL_REGULAR_EXPRESSION
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
foreach(FILENAME validate.py pytest.ini conftest.py)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}
@@ -44,4 +45,4 @@ set_tests_properties(
test-async-copy-tracing-validate
PROPERTIES TIMEOUT 45 LABELS "integration-tests" DEPENDS
test-async-copy-tracing-execute FAIL_REGULAR_EXPRESSION
"threw an exception")
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
+2 -1
Просмотреть файл
@@ -3,7 +3,7 @@
#
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
project(rocprofiler-test-apps LANGUAGES C CXX)
project(rocprofiler-tests-bin LANGUAGES C CXX)
set(CMAKE_BUILD_RPATH "\$ORIGIN:\$ORIGIN/../lib")
@@ -11,6 +11,7 @@ set(CMAKE_BUILD_RPATH "\$ORIGIN:\$ORIGIN/../lib")
add_subdirectory(simple-transpose)
add_subdirectory(multistream)
add_subdirectory(vector-operations)
add_subdirectory(hip-in-libraries)
set(CMAKE_BUILD_RPATH
"\$ORIGIN:\$ORIGIN/../lib:$<TARGET_FILE_DIR:rocprofiler-sdk-roctx::rocprofiler-sdk-roctx-shared-library>"
+34
Просмотреть файл
@@ -0,0 +1,34 @@
#
#
#
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
project(rocprofiler-tests-bin-hip-in-libraries LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(hip-in-libraries)
target_sources(hip-in-libraries PRIVATE hip-in-libraries.cpp)
target_compile_options(hip-in-libraries PRIVATE -W -Wall -Wextra -Wpedantic -Wshadow
-Werror)
target_link_libraries(hip-in-libraries PRIVATE transpose-shared-library
vector-ops-shared-library)
find_package(hip REQUIRED)
target_link_libraries(hip-in-libraries PRIVATE hip::host)
find_package(Threads REQUIRED)
target_link_libraries(hip-in-libraries PRIVATE Threads::Threads)
if(TRANSPOSE_USE_MPI)
find_package(MPI REQUIRED)
target_compile_definitions(hip-in-libraries PRIVATE USE_MPI)
target_link_libraries(hip-in-libraries PRIVATE MPI::MPI_C)
endif()
install(
TARGETS hip-in-libraries
DESTINATION bin
COMPONENT tests)
+151
Просмотреть файл
@@ -0,0 +1,151 @@
// MIT License
//
// Copyright (c) 2023 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 "transpose.hpp"
#include "vector-ops.hpp"
#include <hip/hip_runtime_api.h>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <mutex>
#include <stdexcept>
#include <thread>
#if defined(USE_MPI)
# include <mpi.h>
#endif
#define HIP_API_CALL(CALL) \
{ \
hipError_t error_ = (CALL); \
if(error_ != hipSuccess) \
{ \
auto _hip_api_print_lk = auto_lock_t{print_lock}; \
fprintf(stderr, \
"%s:%d :: HIP error : %s\n", \
__FILE__, \
__LINE__, \
hipGetErrorString(error_)); \
throw std::runtime_error("hip_api_call"); \
} \
}
namespace
{
using auto_lock_t = std::unique_lock<std::mutex>;
auto print_lock = std::mutex{};
size_t nqueues = 8;
size_t nthreads = 4;
size_t nitr = 500;
size_t nsync = 10;
} // namespace
int
main(int argc, char** argv)
{
int rank = 0;
int size = 1;
#if defined(USE_MPI)
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
#else
(void) size;
#endif
for(int i = 1; i < argc; ++i)
{
auto _arg = std::string{argv[i]};
if(_arg == "?" || _arg == "-h" || _arg == "--help")
{
if(rank == 0)
{
fprintf(stderr,
"usage: hip-in-libraries [NUM_QUEUES (%zu)] [NUM_THREADS (%zu)] "
"[NUM_ITERATION (%zu)] "
"[SYNC_EVERY_N_ITERATIONS (%zu)]\n",
nqueues,
nthreads,
nitr,
nsync);
}
exit(EXIT_SUCCESS);
}
}
if(argc > 1) nqueues = atoll(argv[1]);
if(argc > 2) nthreads = atoll(argv[2]);
if(argc > 3) nitr = atoll(argv[3]);
if(argc > 4) nsync = atoll(argv[4]);
int ndevice = 0;
HIP_API_CALL(hipGetDeviceCount(&ndevice));
printf("[hip-in-libraries] Number of devices found: %i\n", ndevice);
printf("[hip-in-libraries] Number of queues: %zu\n", nqueues);
printf("[hip-in-libraries] Number of threads: %zu\n", nthreads);
printf("[hip-in-libraries] Number of iterations: %zu\n", nitr);
printf("[hip-in-libraries] Syncing every %zu iterations\n", nsync);
{
auto vector_ops_thread = std::thread{run_vector_ops, nthreads, nqueues};
auto transpose_thread = std::thread{run_transpose, nthreads, nitr, nsync};
vector_ops_thread.join();
transpose_thread.join();
}
// this is a temporary workaround in omnitrace when HIP + MPI is enabled
#if defined(USE_MPI)
MPI_Barrier(MPI_COMM_WORLD);
#endif
for(int i = 0; i < ndevice; ++i)
{
HIP_API_CALL(hipSetDevice(i));
HIP_API_CALL(hipDeviceSynchronize());
}
#if defined(USE_MPI)
MPI_Barrier(MPI_COMM_WORLD);
#endif
if(rank == 0)
{
for(int i = 0; i < ndevice; ++i)
{
HIP_API_CALL(hipSetDevice(i));
HIP_API_CALL(hipDeviceReset());
}
}
#if defined(USE_MPI)
MPI_Barrier(MPI_COMM_WORLD);
#endif
return 0;
}
+1 -1
Просмотреть файл
@@ -17,7 +17,7 @@ if(NOT CMAKE_HIP_COMPILER)
endif()
endif()
project(rocprofiler-test-app-multistream LANGUAGES CXX HIP)
project(rocprofiler-tests-bin-multistream LANGUAGES CXX HIP)
foreach(_TYPE DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
if("${CMAKE_HIP_FLAGS_${_TYPE}}" STREQUAL "")
+1 -1
Просмотреть файл
@@ -17,7 +17,7 @@ if(NOT CMAKE_HIP_COMPILER)
endif()
endif()
project(rocprofiler-test-app-reproducible-runtime LANGUAGES CXX HIP)
project(rocprofiler-tests-bin-reproducible-runtime LANGUAGES CXX HIP)
foreach(_TYPE DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
if("${CMAKE_HIP_FLAGS_${_TYPE}}" STREQUAL "")
+1 -1
Просмотреть файл
@@ -17,7 +17,7 @@ if(NOT CMAKE_HIP_COMPILER)
endif()
endif()
project(rocprofiler-tool-test-app-transpose LANGUAGES CXX HIP)
project(rocprofiler-tests-bin-transpose LANGUAGES CXX HIP)
foreach(_TYPE DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
if("${CMAKE_HIP_FLAGS_${_TYPE}}" STREQUAL "")
+1 -1
Просмотреть файл
@@ -17,7 +17,7 @@ if(NOT CMAKE_HIP_COMPILER)
endif()
endif()
project(rocprofiler-test-app-transpose LANGUAGES CXX HIP)
project(rocprofiler-tests-bin-transpose LANGUAGES CXX HIP)
foreach(_TYPE DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
if("${CMAKE_HIP_FLAGS_${_TYPE}}" STREQUAL "")
+5 -3
Просмотреть файл
@@ -189,7 +189,7 @@ run(int rank, int tid, int devid, int argc, char** argv)
HIP_API_CALL(hipStreamCreate(&stream));
auto_lock_t _lk{print_lock};
std::cout << "[" << rank << "][" << tid << "] M: " << M << " N: " << N << std::endl;
std::cout << "[transpose][" << rank << "][" << tid << "] M: " << M << " N: " << N << std::endl;
_lk.unlock();
std::default_random_engine _engine{std::random_device{}() * (rank + 1) * (tid + 1)};
@@ -230,8 +230,10 @@ run(int rank, int tid, int devid, int argc, char** argv)
float GB = (float) size * nitr * 2 / (1 << 30);
print_lock.lock();
std::cout << "[" << rank << "][" << tid << "] Runtime of transpose is " << time << " sec\n"
<< "The average performance of transpose is " << GB / time << " GBytes/sec"
std::cout << "[transpose][" << rank << "][" << tid << "] Runtime of transpose is " << time
<< " sec\n";
std::cout << "[transpose][" << rank << "][" << tid
<< "] The average performance of transpose is " << GB / time << " GBytes/sec"
<< std::endl;
print_lock.unlock();
+1 -1
Просмотреть файл
@@ -17,7 +17,7 @@ if(NOT CMAKE_HIP_COMPILER)
endif()
endif()
project(rocprofiler-tool-test-app-transpose LANGUAGES CXX HIP)
project(rocprofiler-tests-bin-vector-operations LANGUAGES CXX HIP)
foreach(_TYPE DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
if("${CMAKE_HIP_FLAGS_${_TYPE}}" STREQUAL "")
+68 -46
Просмотреть файл
@@ -1,24 +1,25 @@
/*
Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved.
// MIT License
//
// Copyright (c) 2023 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.
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 <assert.h>
#include <hip/hip_runtime.h>
#include <stdio.h>
@@ -132,8 +133,12 @@ divide_kernel(float* __restrict__ a,
using namespace std;
void
run(int NUM_QUEUE)
run(int NUM_QUEUE, int DEVICE_ID)
{
HIP_API_CALL(hipSetDevice(DEVICE_ID));
HIP_API_CALL(hipDeviceSynchronize());
std::vector<float*> hostA(NUM_QUEUE);
std::vector<float*> hostB(NUM_QUEUE);
std::vector<float*> hostC(NUM_QUEUE);
@@ -144,10 +149,18 @@ run(int NUM_QUEUE)
std::vector<hipStream_t> streams(NUM_QUEUE);
hipDeviceProp_t devProp;
HIP_API_CALL(hipGetDeviceProperties(&devProp, 0));
auto sync_stream = [NUM_QUEUE, streams](int q) {
if(q < 0 || q >= NUM_QUEUE)
throw std::runtime_error{std::string{"invalid stream id: "} + std::to_string(q)};
int i;
HIP_API_CALL(hipStreamSynchronize(streams.at(q)));
};
auto sync_streams = [NUM_QUEUE, sync_stream]() {
for(int i = 0; i < NUM_QUEUE; ++i)
sync_stream(i);
HIP_API_CALL(hipDeviceSynchronize());
};
for(int q = 0; q < NUM_QUEUE; q++)
{
@@ -158,26 +171,26 @@ run(int NUM_QUEUE)
HIP_API_CALL(hipHostMalloc(&hostC[q], NUM * sizeof(float), 0));
// initialize the input data
for(i = 0; i < NUM; i++)
for(int i = 0; i < NUM; i++)
{
hostB[q][i] = (float) i;
hostC[q][i] = (float) i * 100.0f;
hostB[q][i] = static_cast<float>(i);
hostC[q][i] = static_cast<float>(i * 100.0f);
}
HIP_API_CALL(hipMalloc((void**) (&deviceA[q]), NUM * sizeof(float)));
HIP_API_CALL(hipMalloc((void**) (&deviceB[q]), NUM * sizeof(float)));
HIP_API_CALL(hipMalloc((void**) (&deviceC[q]), NUM * sizeof(float)));
HIP_API_CALL(hipMallocAsync(&deviceA[q], NUM * sizeof(float), streams[q]));
HIP_API_CALL(hipMallocAsync(&deviceB[q], NUM * sizeof(float), streams[q]));
HIP_API_CALL(hipMallocAsync(&deviceC[q], NUM * sizeof(float), streams[q]));
HIP_API_CALL(hipMemcpyAsync(
deviceB[q], hostB[q], NUM * sizeof(float), hipMemcpyHostToDevice, streams[q]));
HIP_API_CALL(hipMemcpyAsync(
deviceC[q], hostC[q], NUM * sizeof(float), hipMemcpyHostToDevice, streams[q]));
}
HIP_API_CALL(hipDeviceSynchronize());
for(int RUN_I = 0; RUN_I < 2; RUN_I++)
sync_streams();
for(int q = 0; q < NUM_QUEUE; q++)
{
int q = (4 * RUN_I + 0) % NUM_QUEUE;
hipLaunchKernelGGL(addition_kernel,
dim3(WIDTH / THREADS_PER_BLOCK_X, HEIGHT / THREADS_PER_BLOCK_Y),
dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y),
@@ -189,8 +202,8 @@ run(int NUM_QUEUE)
WIDTH,
HEIGHT);
HIP_API_CALL(hipDeviceSynchronize());
q = (4 * RUN_I + 1) % NUM_QUEUE;
HIP_API_CALL(hipGetLastError());
hipLaunchKernelGGL(subtract_kernel,
dim3(WIDTH / THREADS_PER_BLOCK_X, HEIGHT / THREADS_PER_BLOCK_Y),
dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y),
@@ -202,8 +215,8 @@ run(int NUM_QUEUE)
WIDTH,
HEIGHT);
HIP_API_CALL(hipDeviceSynchronize());
q = (4 * RUN_I + 2) % NUM_QUEUE;
HIP_API_CALL(hipGetLastError());
hipLaunchKernelGGL(multiply_kernel,
dim3(WIDTH / THREADS_PER_BLOCK_X, HEIGHT / THREADS_PER_BLOCK_Y),
dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y),
@@ -215,8 +228,8 @@ run(int NUM_QUEUE)
WIDTH,
HEIGHT);
HIP_API_CALL(hipDeviceSynchronize());
q = (4 * RUN_I + 3) % NUM_QUEUE;
HIP_API_CALL(hipGetLastError());
hipLaunchKernelGGL(divide_kernel,
dim3(WIDTH / THREADS_PER_BLOCK_X, HEIGHT / THREADS_PER_BLOCK_Y),
dim3(THREADS_PER_BLOCK_X, THREADS_PER_BLOCK_Y),
@@ -227,17 +240,18 @@ run(int NUM_QUEUE)
deviceC[q],
WIDTH,
HEIGHT);
HIP_API_CALL(hipDeviceSynchronize());
HIP_API_CALL(hipGetLastError());
}
for(int q = 0; q < NUM_QUEUE; q++)
HIP_API_CALL(hipMemcpyAsync(
hostA[q], deviceA[q], NUM * sizeof(float), hipMemcpyDeviceToHost, streams[q]));
sync_streams();
for(int q = 0; q < NUM_QUEUE; q++)
{
HIP_API_CALL(hipMemcpy(hostA[q], deviceA[q], NUM * sizeof(float), hipMemcpyDeviceToHost));
HIP_API_CALL(hipDeviceSynchronize());
HIP_API_CALL(hipMemcpyAsync(
hostA[q], deviceA[q], NUM * sizeof(float), hipMemcpyDeviceToHost, streams[q]));
sync_stream(q);
HIP_API_CALL(hipFree(deviceA[q]));
HIP_API_CALL(hipFree(deviceB[q]));
@@ -246,13 +260,21 @@ run(int NUM_QUEUE)
HIP_API_CALL(hipHostFree(hostA[q]));
HIP_API_CALL(hipHostFree(hostB[q]));
HIP_API_CALL(hipHostFree(hostC[q]));
HIP_API_CALL(hipStreamDestroy(streams[q]));
}
HIP_API_CALL(hipDeviceSynchronize());
}
int
main()
{
run(1);
int device_count = 0;
HIP_API_CALL(hipGetDeviceCount(&device_count));
for(int i = 0; i < device_count; ++i)
run(4, i);
return 0;
}
+1 -1
Просмотреть файл
@@ -35,4 +35,4 @@ set_tests_properties(
PASS_REGULAR_EXPRESSION
"Test C tool is using rocprofiler-sdk v([0-9]+\\.[0-9]+\\.[0-9]+)"
FAIL_REGULAR_EXPRESSION
"threw an exception")
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
+5
Просмотреть файл
@@ -6,6 +6,11 @@ include(FetchContent)
set(FETCHCONTENT_BASE_DIR ${PROJECT_BINARY_DIR}/external)
# default FAIL_REGULAR_EXPRESSION for tests
set(ROCPROFILER_DEFAULT_FAIL_REGEX
"threw an exception|Permission denied|Could not create logging file"
CACHE STRING "Default FAIL_REGULAR_EXPRESSION for tests")
# build flags
add_library(rocprofiler-tests-build-flags INTERFACE)
add_library(rocprofiler::tests-build-flags ALIAS rocprofiler-tests-build-flags)
+2 -2
Просмотреть файл
@@ -29,7 +29,7 @@ set_tests_properties(
ENVIRONMENT
"${PRELOAD_ENV};HSA_TOOLS_LIB=$<TARGET_FILE:rocprofiler::rocprofiler-shared-library>;ROCPROFILER_TOOL_OUTPUT_FILE=counter-collection-test.json;ROCPROFILER_TOOL_CONTEXTS=COUNTER_COLLECTION;ROCPROF_COUNTERS=SQ_WAVES_sum"
FAIL_REGULAR_EXPRESSION
"threw an exception")
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
foreach(FILENAME validate.py pytest.ini conftest.py)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}
@@ -44,4 +44,4 @@ set_tests_properties(
test-counter-collection-validate
PROPERTIES TIMEOUT 45 LABELS "integration-tests" DEPENDS
test-counter-collection-execute FAIL_REGULAR_EXPRESSION
"threw an exception")
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
+2 -2
Просмотреть файл
@@ -34,7 +34,7 @@ set(kernel-tracing-env
set_tests_properties(
test-kernel-tracing-execute
PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT "${kernel-tracing-env}"
FAIL_REGULAR_EXPRESSION "threw an exception")
FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}")
foreach(FILENAME validate.py pytest.ini conftest.py)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}
@@ -49,4 +49,4 @@ add_test(
set_tests_properties(
test-kernel-tracing-validate
PROPERTIES TIMEOUT 45 LABELS "integration-tests" DEPENDS test-kernel-tracing-execute
FAIL_REGULAR_EXPRESSION "threw an exception")
FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}")
+18
Просмотреть файл
@@ -0,0 +1,18 @@
#
# Integration test application libraries
#
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
project(rocprofiler-tests-lib LANGUAGES C CXX)
set(CMAKE_BUILD_RPATH "\$ORIGIN:\$ORIGIN/../lib")
# libraries used by integration test apps which DO NOT link to rocprofiler-sdk-roctx
add_subdirectory(vector-operations)
set(CMAKE_BUILD_RPATH
"\$ORIGIN:\$ORIGIN/../lib:$<TARGET_FILE_DIR:rocprofiler-sdk-roctx::rocprofiler-sdk-roctx-shared-library>"
)
# libraries used by integration test apps which DO link to rocprofiler-sdk-roctx
add_subdirectory(transpose)
+61
Просмотреть файл
@@ -0,0 +1,61 @@
#
#
#
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
if(NOT CMAKE_HIP_COMPILER)
find_program(
amdclangpp_EXECUTABLE
NAMES amdclang++
HINTS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
PATHS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
PATH_SUFFIXES bin llvm/bin NO_CACHE)
mark_as_advanced(amdclangpp_EXECUTABLE)
if(amdclangpp_EXECUTABLE)
set(CMAKE_HIP_COMPILER "${amdclangpp_EXECUTABLE}")
endif()
endif()
project(rocprofiler-tests-lib-transpose-shared-library LANGUAGES CXX HIP)
foreach(_TYPE DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
if("${CMAKE_HIP_FLAGS_${_TYPE}}" STREQUAL "")
set(CMAKE_HIP_FLAGS_${_TYPE} "${CMAKE_CXX_FLAGS_${_TYPE}}")
endif()
endforeach()
option(TRANSPOSE_USE_MPI "Enable MPI support in transpose-shared-library exe" OFF)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_HIP_STANDARD 17)
set(CMAKE_HIP_EXTENSIONS OFF)
set(CMAKE_HIP_STANDARD_REQUIRED ON)
set_source_files_properties(transpose.cpp PROPERTIES LANGUAGE HIP)
add_library(transpose-shared-library SHARED)
target_sources(transpose-shared-library PRIVATE transpose.cpp)
target_compile_options(transpose-shared-library PRIVATE -W -Wall -Wextra -Wpedantic
-Wshadow -Werror)
target_include_directories(transpose-shared-library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(transpose-shared-library PROPERTIES OUTPUT_NAME transpose)
find_package(Threads REQUIRED)
target_link_libraries(transpose-shared-library PRIVATE Threads::Threads)
find_package(rocprofiler-sdk-roctx REQUIRED)
target_link_libraries(transpose-shared-library
PRIVATE rocprofiler-sdk-roctx::rocprofiler-sdk-roctx)
if(TRANSPOSE_USE_MPI)
find_package(MPI REQUIRED)
target_compile_definitions(transpose-shared-library PRIVATE USE_MPI)
target_link_libraries(transpose-shared-library PRIVATE MPI::MPI_C)
endif()
install(
TARGETS transpose-shared-library
DESTINATION lib
COMPONENT tests)
+260
Просмотреть файл
@@ -0,0 +1,260 @@
// MIT License
//
// Copyright (c) 2023 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-sdk-roctx/roctx.h"
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <mutex>
#include <random>
#include <stdexcept>
#if defined(USE_MPI)
# include <mpi.h>
#endif
#define HIP_API_CALL(CALL) \
{ \
hipError_t error_ = (CALL); \
if(error_ != hipSuccess) \
{ \
auto _hip_api_print_lk = auto_lock_t{print_lock}; \
fprintf(stderr, \
"%s:%d :: HIP error : %s\n", \
__FILE__, \
__LINE__, \
hipGetErrorString(error_)); \
throw std::runtime_error("hip_api_call"); \
} \
}
namespace
{
using auto_lock_t = std::unique_lock<std::mutex>;
auto print_lock = std::mutex{};
constexpr unsigned shared_mem_tile_dim = 32;
void
check_hip_error(void);
void
verify(int* in, int* out, int M, int N);
__global__ void
transpose(const int* in, int* out, int M, int N);
void
run_transpose_impl(int rank, int tid, int ndevice, size_t nitr, size_t nsync);
__global__ void
transpose(const int* in, int* out, int M, int N)
{
__shared__ int tile[shared_mem_tile_dim][shared_mem_tile_dim];
int idx = (blockIdx.y * blockDim.y + threadIdx.y) * M + blockIdx.x * blockDim.x + threadIdx.x;
tile[threadIdx.y][threadIdx.x] = in[idx];
__syncthreads();
idx = (blockIdx.x * blockDim.x + threadIdx.y) * N + blockIdx.y * blockDim.y + threadIdx.x;
out[idx] = tile[threadIdx.x][threadIdx.y];
}
void
run_transpose_impl(int rank, int tid, int devid, size_t nitr, size_t nsync)
{
roctxRangePush("run_transpose_impl");
constexpr unsigned int M = 4960 * 2;
constexpr unsigned int N = 4960 * 2;
hipStream_t stream = {};
printf("[transpose] Rank %i, thread %i assigned to device %i\n", rank, tid, devid);
HIP_API_CALL(hipSetDevice(devid));
HIP_API_CALL(hipStreamCreate(&stream));
auto_lock_t _lk{print_lock};
std::cout << "[transpose][" << rank << "][" << tid << "] M: " << M << " N: " << N << std::endl;
_lk.unlock();
std::default_random_engine _engine{std::random_device{}() * (rank + 1) * (tid + 1)};
std::uniform_int_distribution<int> _dist{0, 1000};
size_t size = sizeof(int) * M * N;
int* inp_matrix = new int[size];
int* out_matrix = new int[size];
for(size_t i = 0; i < M * N; i++)
{
inp_matrix[i] = _dist(_engine);
out_matrix[i] = 0;
}
int* in = nullptr;
int* out = nullptr;
HIP_API_CALL(hipMalloc(&in, size));
HIP_API_CALL(hipMalloc(&out, size));
HIP_API_CALL(hipMemsetAsync(in, 0, size, stream));
HIP_API_CALL(hipMemsetAsync(out, 0, size, stream));
HIP_API_CALL(hipMemcpyAsync(in, inp_matrix, size, hipMemcpyHostToDevice, stream));
HIP_API_CALL(hipStreamSynchronize(stream));
dim3 grid(M / 32, N / 32, 1);
dim3 block(32, 32, 1); // transpose
auto t1 = std::chrono::high_resolution_clock::now();
for(size_t i = 0; i < nitr; ++i)
{
transpose<<<grid, block, 0, stream>>>(in, out, M, N);
check_hip_error();
if(i % nsync == (nsync - 1)) HIP_API_CALL(hipStreamSynchronize(stream));
}
auto t2 = std::chrono::high_resolution_clock::now();
HIP_API_CALL(hipStreamSynchronize(stream));
HIP_API_CALL(hipMemcpyAsync(out_matrix, out, size, hipMemcpyDeviceToHost, stream));
double time = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1).count();
float GB = (float) size * nitr * 2 / (1 << 30);
print_lock.lock();
std::cout << "[transpose][" << rank << "][" << tid << "] Runtime of transpose is " << time
<< " sec\n";
std::cout << "[transpose][" << rank << "][" << tid
<< "] The average performance of transpose is " << GB / time << " GBytes/sec"
<< std::endl;
print_lock.unlock();
HIP_API_CALL(hipStreamSynchronize(stream));
HIP_API_CALL(hipStreamDestroy(stream));
// cpu_transpose(matrix, out_matrix, M, N);
verify(inp_matrix, out_matrix, M, N);
HIP_API_CALL(hipFree(in));
HIP_API_CALL(hipFree(out));
delete[] inp_matrix;
delete[] out_matrix;
roctxRangePop();
}
void
check_hip_error(void)
{
hipError_t err = hipGetLastError();
if(err != hipSuccess)
{
auto_lock_t _lk{print_lock};
std::cerr << "Error: " << hipGetErrorString(err) << std::endl;
throw std::runtime_error("hip_api_call");
}
}
void
verify(int* in, int* out, int M, int N)
{
for(int i = 0; i < 10; i++)
{
int row = rand() % M;
int col = rand() % N;
if(in[row * N + col] != out[col * M + row])
{
auto_lock_t _lk{print_lock};
std::cout << "mismatch: " << row << ", " << col << " : " << in[row * N + col] << " | "
<< out[col * M + row] << "\n";
}
}
}
} // namespace
void
run_transpose(size_t nthreads, size_t nitr, size_t nsync)
{
auto range_id = roctxRangeStart("run_transpose");
int rank = 0;
int size = 1;
printf("[transpose] Number of threads: %zu\n", nthreads);
printf("[transpose] Number of iterations: %zu\n", nitr);
printf("[transpose] Syncing every %zu iterations\n", nsync);
#if defined(USE_MPI)
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
#else
(void) size;
#endif
// this is a temporary workaround in omnitrace when HIP + MPI is enabled
int ndevice = 0;
HIP_API_CALL(hipGetDeviceCount(&ndevice));
printf("[transpose] Number of devices found: %i\n", ndevice);
auto devids = std::vector<int>{};
devids.resize(size * nthreads, 0);
int devid = 0;
for(size_t i = 0; i < nthreads; ++i)
{
for(int j = 0; j < size; ++j)
{
auto idx = (j * nthreads) + i;
devids.at(idx) = devid++ % ndevice;
}
}
auto devid_offset = (rank * nthreads);
auto _threads = std::vector<std::thread>{};
for(size_t i = 1; i < nthreads; ++i)
_threads.emplace_back(
run_transpose_impl, rank, i, devids.at(devid_offset + i), nitr, nsync);
run_transpose_impl(rank, 0, devids.at(devid_offset + 0), nitr, nsync);
for(auto& itr : _threads)
itr.join();
#if defined(USE_MPI)
MPI_Barrier(MPI_COMM_WORLD);
#endif
// for(int i = 0; i < ndevice; ++i)
// {
// HIP_API_CALL(hipSetDevice(i));
// HIP_API_CALL(hipDeviceSynchronize());
// }
// #if defined(USE_MPI)
// MPI_Barrier(MPI_COMM_WORLD);
// #endif
// if(rank == 0)
// {
// for(int i = 0; i < ndevice; ++i)
// {
// HIP_API_CALL(hipSetDevice(i));
// HIP_API_CALL(hipDeviceReset());
// }
// }
// #if defined(USE_MPI)
// MPI_Barrier(MPI_COMM_WORLD);
// #endif
roctxRangeStop(range_id);
}
+28
Просмотреть файл
@@ -0,0 +1,28 @@
// MIT License
//
// Copyright (c) 2023 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.
#pragma once
#include <cstddef>
void
run_transpose(size_t nthreads, size_t nitr, size_t nsync);
+49
Просмотреть файл
@@ -0,0 +1,49 @@
#
#
#
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
if(NOT CMAKE_HIP_COMPILER)
find_program(
amdclangpp_EXECUTABLE
NAMES amdclang++
HINTS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
PATHS ${ROCM_PATH} ENV ROCM_PATH /opt/rocm
PATH_SUFFIXES bin llvm/bin NO_CACHE)
mark_as_advanced(amdclangpp_EXECUTABLE)
if(amdclangpp_EXECUTABLE)
set(CMAKE_HIP_COMPILER "${amdclangpp_EXECUTABLE}")
endif()
endif()
project(rocprofiler-tests-lib-vector-operations LANGUAGES CXX HIP)
foreach(_TYPE DEBUG MINSIZEREL RELEASE RELWITHDEBINFO)
if("${CMAKE_HIP_FLAGS_${_TYPE}}" STREQUAL "")
set(CMAKE_HIP_FLAGS_${_TYPE} "${CMAKE_CXX_FLAGS_${_TYPE}}")
endif()
endforeach()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_HIP_STANDARD 17)
set(CMAKE_HIP_EXTENSIONS OFF)
set(CMAKE_HIP_STANDARD_REQUIRED ON)
set_source_files_properties(vector-ops.cpp PROPERTIES LANGUAGE HIP)
add_library(vector-ops-shared-library SHARED)
target_sources(vector-ops-shared-library PRIVATE vector-ops.cpp)
target_compile_options(vector-ops-shared-library PRIVATE -W -Wall -Wextra -Wpedantic
-Wshadow -Werror)
target_include_directories(vector-ops-shared-library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(vector-ops-shared-library PROPERTIES OUTPUT_NAME vector-ops)
find_package(Threads REQUIRED)
target_link_libraries(vector-ops-shared-library PRIVATE Threads::Threads)
install(
TARGETS vector-ops-shared-library
DESTINATION lib
COMPONENT tests)
+291
Просмотреть файл
@@ -0,0 +1,291 @@
// MIT License
//
// Copyright (c) 2023 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 <assert.h>
#include <hip/hip_runtime.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <algorithm>
#include <iostream>
#include <mutex>
#include <vector>
#define HIP_API_CALL(CALL) \
{ \
hipError_t error_ = (CALL); \
if(error_ != hipSuccess) \
{ \
auto _hip_api_print_lk = auto_lock_t{print_lock}; \
fprintf(stderr, \
"%s:%d :: HIP error : %s\n", \
__FILE__, \
__LINE__, \
hipGetErrorString(error_)); \
throw std::runtime_error("hip_api_call"); \
} \
}
namespace
{
using auto_lock_t = std::unique_lock<std::mutex>;
auto print_lock = std::mutex{};
constexpr auto WIDTH = (1 << 12); // 4096
constexpr auto HEIGHT = (1 << 11); // 2048
constexpr auto DEPTH = (1 << 0); // 1
constexpr auto NUM = (WIDTH * HEIGHT * DEPTH);
struct dimensions
{
int x = 1;
int y = 1;
int z = 1;
};
constexpr auto threads_per_block = dimensions{64, 1, 1};
// Computes vectorAdd with matrix-multiply
template <typename Tp>
__global__ void
addition_kernel(Tp* __restrict__ a,
const Tp* __restrict__ b,
const Tp* __restrict__ c,
int width,
int /*height*/)
{
// printf("addition kernel\n");
int x = blockDim.x * blockIdx.x + threadIdx.x;
int y = blockDim.y * blockIdx.y + threadIdx.y;
if(x >= WIDTH || y >= HEIGHT) return;
int index = y * width + x;
a[index] = b[index] + c[index];
}
template <typename Tp>
__global__ void
subtract_kernel(Tp* __restrict__ a,
const Tp* __restrict__ b,
const Tp* __restrict__ c,
int width,
int /*height*/)
{
// printf("subtract kernel\n");
int x = blockDim.x * blockIdx.x + threadIdx.x;
int y = blockDim.y * blockIdx.y + threadIdx.y;
if(x >= WIDTH || y >= HEIGHT) return;
int index = y * width + x;
a[index] = abs(b[index] - c[index]);
}
template <typename Tp>
__global__ void
multiply_kernel(Tp* __restrict__ a,
const Tp* __restrict__ b,
const Tp* __restrict__ c,
int width,
int /*height*/)
{
// printf("multiply kernel\n");
int x = blockDim.x * blockIdx.x + threadIdx.x;
int y = blockDim.y * blockIdx.y + threadIdx.y;
if(x >= WIDTH || y >= HEIGHT) return;
int index = y * width + x;
a[index] = (b[index] - 1) * (c[index] - 1) + 1;
}
template <typename Tp>
__global__ void
divide_kernel(Tp* __restrict__ a,
const Tp* __restrict__ b,
const Tp* __restrict__ c,
int width,
int /*height*/)
{
// printf("divide kernel\n");
int x = blockDim.x * blockIdx.x + threadIdx.x;
int y = blockDim.y * blockIdx.y + threadIdx.y;
if(x >= WIDTH || y >= HEIGHT) return;
int index = y * width + x;
a[index] = (b[index] - c[index]) / abs(c[index] + b[index]) + 1;
}
void
run_vector_ops_impl(int num_queue, int device_id)
{
auto t1 = std::chrono::high_resolution_clock::now();
HIP_API_CALL(hipSetDevice(device_id));
std::vector<float*> hostA(num_queue);
std::vector<float*> hostB(num_queue);
std::vector<float*> hostC(num_queue);
std::vector<float*> deviceA(num_queue);
std::vector<float*> deviceB(num_queue);
std::vector<float*> deviceC(num_queue);
std::vector<hipStream_t> streams(num_queue);
auto sync_stream = [num_queue, streams](int q) {
if(q < 0 || q >= num_queue)
throw std::runtime_error{std::string{"invalid stream id: "} + std::to_string(q)};
HIP_API_CALL(hipStreamSynchronize(streams.at(q)));
};
auto sync_streams = [num_queue, sync_stream]() {
for(int i = 0; i < num_queue; ++i)
sync_stream(i);
};
for(int q = 0; q < num_queue; q++)
{
HIP_API_CALL(hipStreamCreateWithFlags(&streams[q], hipStreamNonBlocking));
HIP_API_CALL(hipHostMalloc(&hostA[q], NUM * sizeof(float), 0));
HIP_API_CALL(hipHostMalloc(&hostB[q], NUM * sizeof(float), 0));
HIP_API_CALL(hipHostMalloc(&hostC[q], NUM * sizeof(float), 0));
// initialize the input data
for(int i = 0; i < NUM; i++)
{
hostB[q][i] = static_cast<float>(i);
hostC[q][i] = static_cast<float>(i * 100.0f);
}
HIP_API_CALL(hipMallocAsync(&deviceA[q], NUM * sizeof(float), streams[q]));
HIP_API_CALL(hipMallocAsync(&deviceB[q], NUM * sizeof(float), streams[q]));
HIP_API_CALL(hipMallocAsync(&deviceC[q], NUM * sizeof(float), streams[q]));
HIP_API_CALL(hipMemcpyAsync(
deviceB[q], hostB[q], NUM * sizeof(float), hipMemcpyHostToDevice, streams[q]));
HIP_API_CALL(hipMemcpyAsync(
deviceC[q], hostC[q], NUM * sizeof(float), hipMemcpyHostToDevice, streams[q]));
}
sync_streams();
for(int q = 0; q < num_queue; q++)
{
hipLaunchKernelGGL(addition_kernel,
dim3(WIDTH / threads_per_block.x, HEIGHT / threads_per_block.y),
dim3(threads_per_block.x, threads_per_block.y),
0,
streams[q],
deviceA[q],
deviceB[q],
deviceC[q],
WIDTH,
HEIGHT);
hipLaunchKernelGGL(subtract_kernel,
dim3(WIDTH / threads_per_block.x, HEIGHT / threads_per_block.y),
dim3(threads_per_block.x, threads_per_block.y),
0,
streams[q],
deviceA[q],
deviceB[q],
deviceC[q],
WIDTH,
HEIGHT);
hipLaunchKernelGGL(multiply_kernel,
dim3(WIDTH / threads_per_block.x, HEIGHT / threads_per_block.y),
dim3(threads_per_block.x, threads_per_block.y),
0,
streams[q],
deviceA[q],
deviceB[q],
deviceC[q],
WIDTH,
HEIGHT);
hipLaunchKernelGGL(divide_kernel,
dim3(WIDTH / threads_per_block.x, HEIGHT / threads_per_block.y),
dim3(threads_per_block.x, threads_per_block.y),
0,
streams[q],
deviceB[q],
deviceA[q],
deviceC[q],
WIDTH,
HEIGHT);
}
sync_streams();
for(int q = 0; q < num_queue; q++)
{
HIP_API_CALL(hipMemcpyAsync(
hostA[q], deviceA[q], NUM * sizeof(float), hipMemcpyDeviceToHost, streams[q]));
sync_stream(q);
HIP_API_CALL(hipFree(deviceA[q]));
HIP_API_CALL(hipFree(deviceB[q]));
HIP_API_CALL(hipFree(deviceC[q]));
HIP_API_CALL(hipHostFree(hostA[q]));
HIP_API_CALL(hipHostFree(hostB[q]));
HIP_API_CALL(hipHostFree(hostC[q]));
HIP_API_CALL(hipStreamDestroy(streams[q]));
}
auto t2 = std::chrono::high_resolution_clock::now();
double time = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1).count();
print_lock.lock();
std::cout << "[vector-ops] Runtime of vector-ops is " << time << " sec\n";
print_lock.unlock();
}
} // namespace
void
run_vector_ops(int num_threads, int num_queue)
{
int device_count = 0;
HIP_API_CALL(hipGetDeviceCount(&device_count));
if(device_count == 0) throw std::runtime_error{"No HIP devices found"};
num_threads = std::max<int>(num_threads, 1);
num_queue = std::max<int>(num_queue, 1);
auto _threads = std::vector<std::thread>{};
_threads.reserve(num_threads);
for(int i = 0; i < num_threads; ++i)
_threads.emplace_back(run_vector_ops_impl, num_queue, i % device_count);
for(auto& itr : _threads)
itr.join();
}
+26
Просмотреть файл
@@ -0,0 +1,26 @@
// MIT License
//
// Copyright (c) 2023 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.
#pragma once
void
run_vector_ops(int num_threads, int num_queue);
+2 -1
Просмотреть файл
@@ -24,5 +24,6 @@ enable_testing()
include(CTest)
add_subdirectory(tracing)
add_subdirectory(counter-collection)
add_subdirectory(tracing-plus-cc)
add_subdirectory(tracing-hip-in-libraries)
add_subdirectory(counter-collection)
+4
Просмотреть файл
@@ -1,3 +1,7 @@
#
# Various counter collection tests
#
foreach(FILENAME conftest.py pytest.ini)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}
${CMAKE_CURRENT_BINARY_DIR}/${FILENAME} COPYONLY)
+2 -2
Просмотреть файл
@@ -40,7 +40,7 @@ set(cc-env-pmc1
set_tests_properties(
rocprofv3-test-counter-collection-pmc1-execute
PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT "${cc-env-pmc1}"
FAIL_REGULAR_EXPRESSION "threw an exception")
FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}")
add_test(NAME rocprofv3-test-counter-collection-pmc1-validate
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/validate.py --input
@@ -50,4 +50,4 @@ set_tests_properties(
rocprofv3-test-counter-collection-pmc1-validate
PROPERTIES TIMEOUT 45 LABELS "integration-tests" DEPENDS
rocprofv3-test-counter-collection-pmc1-execute FAIL_REGULAR_EXPRESSION
"threw an exception")
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
+30 -14
Просмотреть файл
@@ -1,30 +1,46 @@
import pandas as pd
#!/usr/bin/env python3
import sys
import pytest
import numpy as np
import pandas as pd
kernel_list = ["addition_kernel", "subtract_kernel", "multiply_kernel", "divide_kernel"]
kernel_list = sorted(
["addition_kernel", "subtract_kernel", "multiply_kernel", "divide_kernel"]
)
def unique(lst):
return list(set(lst))
def test_validate_counter_collection_pmc1(input_data: pd.DataFrame):
df = input_data
assert df.empty == False
assert not df.empty
assert (df["Agent_Id"].astype(int).values > 0).all()
assert (df["Queue_Id"].astype(int).values > 0).all()
assert (df["Process_Id"].astype(int).values > 0).all()
assert len(df["Kernel-Name"]) > 0
df_list = df["Kernel-Name"].values.flatten().tolist()
# Check if each string in kernel_list is present at least once
missing_kernels = []
for kernel in kernel_list:
if kernel not in df_list:
missing_kernels.append(kernel)
assert len(df["Kernel_Name"]) > 0
assert kernel_list == sorted(df["Kernel_Name"].unique().tolist())
kernel_count = dict([[itr, 0] for itr in kernel_list])
assert len(kernel_count) == len(kernel_list)
for itr in df["Kernel_Name"]:
kernel_count[itr] += 1
kn_cnt = [itr for _, itr in kernel_count.items()]
assert min(kn_cnt) == max(kn_cnt) and len(unique(kn_cnt)) == 1
assert (
not missing_kernels
), f"The following kernel names are missing from the out file: {missing_kernels}"
assert df["Counter_Name"].str.contains("SQ_WAVES").all()
assert len(df["Counter_Value"]) > 0
assert df["Counter_Name"].str.contains("SQ_WAVES").all()
assert (df["Counter_Value"].astype(int).values > 0).all()
di_list = df["Dispatch_Id"].astype(int).values.tolist()
di_uniq = sorted(df["Dispatch_Id"].unique().tolist())
# make sure the dispatch ids are unique and ordered
di_expect = [idx + 1 for idx in range(len(di_list))]
assert di_expect == di_uniq
if __name__ == "__main__":
+2 -2
Просмотреть файл
@@ -40,7 +40,7 @@ set(cc-env-pmc2
set_tests_properties(
rocprofv3-test-counter-collection-pmc2-execute
PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT "${cc-env-pmc2}"
FAIL_REGULAR_EXPRESSION "threw an exception")
FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}")
add_test(NAME rocprofv3-test-counter-collection-pmc2-validate
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/validate.py
@@ -50,4 +50,4 @@ set_tests_properties(
rocprofv3-test-counter-collection-pmc2-validate
PROPERTIES TIMEOUT 45 LABELS "integration-tests" DEPENDS
rocprofv3-test-counter-collection-pmc2-execute FAIL_REGULAR_EXPRESSION
"threw an exception")
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
+1 -1
Просмотреть файл
@@ -34,7 +34,7 @@ def test_validate_counter_collection_pmc2(input_dir: pd.DataFrame):
with open(file_path, "r") as file:
df = pd.read_csv(file)
# check if kernel-name is present
assert len(df["Kernel-Name"]) > 0
assert len(df["Kernel_Name"]) > 0
# check if counter value is positive
assert len(df["Counter_Value"]) > 0
+2 -2
Просмотреть файл
@@ -41,7 +41,7 @@ set(cc-env-list-metrics
set_tests_properties(
rocprofv3-test-list-metrics-execute
PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT "${cc-env-list-metrics}"
FAIL_REGULAR_EXPRESSION "threw an exception")
FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}")
set_tests_properties(
rocprofv3-test-list-metrics-std-out-execute
@@ -76,6 +76,6 @@ set_tests_properties(
DEPENDS
rocprofv3-test-list-metrics-execute
FAIL_REGULAR_EXPRESSION
"threw an exception"
"${ROCPROFILER_DEFAULT_FAIL_REGEX}"
ATTACHED_FILES_ON_FAIL
"${VALIDATION_FILES}")
+1
Просмотреть файл
@@ -3,3 +3,4 @@
addopts = --durations=20 -rA -s -vv
testpaths = input1/validate.py
input2/validate.py
list_metrics/validate.py
+72
Просмотреть файл
@@ -0,0 +1,72 @@
#
# rocprofv3 tool test
#
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
project(
rocprofiler-tests-rocprofv3-tracing-hip-in-libraries
LANGUAGES CXX
VERSION 0.0.0)
find_package(rocprofiler-sdk REQUIRED)
add_test(
NAME rocprofv3-test-trace-hip-in-libraries-execute
COMMAND
$<TARGET_FILE:rocprofiler-sdk::rocprofv3> --hip-runtime-trace
--hip-compiler-trace --hsa-core-trace --hsa-amd-trace --hsa-image-trace
--hsa-finalizer-trace --kernel-trace --memory-copy-trace -d
${CMAKE_CURRENT_BINARY_DIR}/%argt%-trace -o out $<TARGET_FILE:hip-in-libraries>)
string(REPLACE "LD_PRELOAD=" "ROCPROF_PRELOAD=" PRELOAD_ENV
"${ROCPROFILER_MEMCHECK_PRELOAD_ENV}")
set(tracing-env "${PRELOAD_ENV}"
"HSA_TOOLS_LIB=$<TARGET_FILE:rocprofiler::rocprofiler-shared-library>")
set_tests_properties(
rocprofv3-test-trace-hip-in-libraries-execute
PROPERTIES
LABELS
"integration-tests"
ENVIRONMENT
"${tracing-env}"
FAIL_REGULAR_EXPRESSION
"HSA_CORE_API|HSA_AMD_EXT_API|HSA_IMAGE_EXT_API|HSA_FINALIZER_EXT_API|HIP_API|HIP_COMPILER_API|KERNEL_DISPATCH|CODE_OBJECT"
)
foreach(FILENAME validate.py conftest.py)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}
${CMAKE_CURRENT_BINARY_DIR}/${FILENAME} COPYONLY)
endforeach()
add_test(
NAME rocprofv3-test-trace-hip-in-libraries-validate
COMMAND
${Python3_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/validate.py --hsa-input
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_hsa_api_trace.csv
--hip-input
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_hip_api_trace.csv
--kernel-input
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_kernel_trace.csv
--memory-copy-input
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_memory_copy_trace.csv)
set(VALIDATION_FILES
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_memory_copy_trace.csv
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_hsa_api_trace.csv
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_hip_api_trace.csv
${CMAKE_CURRENT_BINARY_DIR}/hip-in-libraries-trace/out_kernel_trace.csv)
set_tests_properties(
rocprofv3-test-trace-hip-in-libraries-validate
PROPERTIES TIMEOUT
45
LABELS
"integration-tests"
DEPENDS
rocprofv3-test-trace-hip-in-libraries-execute
FAIL_REGULAR_EXPRESSION
"AssertionError"
ATTACHED_FILES_ON_FAIL
"${VALIDATION_FILES}")
+94
Просмотреть файл
@@ -0,0 +1,94 @@
#!/usr/bin/env python3
import os
import csv
import pytest
def pytest_addoption(parser):
parser.addoption(
"--hsa-input",
action="store",
help="Path to HSA API tracing CSV file.",
)
parser.addoption(
"--kernel-input",
action="store",
help="Path to kernel tracing CSV file.",
)
parser.addoption(
"--memory-copy-input",
action="store",
help="Path to memory-copy tracing CSV file.",
)
parser.addoption(
"--marker-input",
action="store",
help="Path to marker API tracing CSV file.",
)
parser.addoption(
"--hip-input",
action="store",
help="Path to HIP runtime and compiler API tracing CSV file.",
)
@pytest.fixture
def hsa_input_data(request):
filename = request.config.getoption("--hsa-input")
data = []
with open(filename, "r") as inp:
reader = csv.DictReader(inp)
for row in reader:
data.append(row)
return data
@pytest.fixture
def kernel_input_data(request):
filename = request.config.getoption("--kernel-input")
data = []
with open(filename, "r") as inp:
reader = csv.DictReader(inp)
for row in reader:
data.append(row)
return data
@pytest.fixture
def memory_copy_input_data(request):
filename = request.config.getoption("--memory-copy-input")
data = []
with open(filename, "r") as inp:
reader = csv.DictReader(inp)
for row in reader:
data.append(row)
return data
@pytest.fixture
def marker_input_data(request):
filename = request.config.getoption("--marker-input")
data = []
with open(filename, "r") as inp:
reader = csv.DictReader(inp)
for row in reader:
data.append(row)
return data
@pytest.fixture
def hip_input_data(request):
filename = request.config.getoption("--hip-input")
data = []
if os.path.exists(filename):
with open(filename, "r") as inp:
reader = csv.DictReader(inp)
for row in reader:
data.append(row)
return data
+142
Просмотреть файл
@@ -0,0 +1,142 @@
#!/usr/bin/env python3
import sys
import pytest
class dim3(object):
def __init__(self, x, y, z):
self.x = int(x)
self.y = int(y)
self.z = int(z)
def as_tuple(self):
return (self.x, self.y, self.z)
def test_api_trace(hsa_input_data, hip_input_data):
functions = []
correlation_ids = []
for row in hsa_input_data:
assert row["Domain"] in (
"HSA_CORE_API",
"HSA_AMD_EXT_API",
"HSA_IMAGE_EXT_API",
"HSA_FINALIZE_EXT_API",
)
assert int(row["Process_Id"]) > 0
assert int(row["Thread_Id"]) >= int(row["Process_Id"])
assert int(row["End_Timestamp"]) >= int(row["Start_Timestamp"])
functions.append(row["Function"])
correlation_ids.append(int(row["Correlation_Id"]))
for row in hip_input_data:
assert row["Domain"] in [
"HIP_RUNTIME_API",
"HIP_COMPILER_API",
]
assert int(row["Process_Id"]) > 0
assert int(row["Thread_Id"]) == 0 or int(row["Thread_Id"]) >= int(
row["Process_Id"]
)
assert int(row["End_Timestamp"]) >= int(row["Start_Timestamp"])
functions.append(row["Function"])
correlation_ids.append(int(row["Correlation_Id"]))
correlation_ids = sorted(list(set(correlation_ids)))
# all correlation ids are unique
assert len(correlation_ids) == (len(hsa_input_data) + len(hip_input_data))
# correlation ids are numbered from 1 to N
assert correlation_ids[0] == 1
assert correlation_ids[-1] == len(correlation_ids)
functions = list(set(functions))
for itr in (
"hsa_amd_memory_async_copy_on_engine",
"hsa_agent_get_info",
"hsa_agent_iterate_isas",
"hsa_signal_create",
"hsa_agent_get_info",
"hsa_executable_symbol_get_info",
):
assert itr in functions
if hip_input_data:
for itr in (
"hipGetLastError",
"hipLaunchKernel",
"hipStreamSynchronize",
"hipMemcpyAsync",
"hipFree",
"hipStreamDestroy",
"hipDeviceSynchronize",
"hipDeviceReset",
"hipSetDevice",
):
assert itr in functions
def test_kernel_trace(kernel_input_data):
valid_kernel_names = sorted(
[
"__amd_rocclr_fillBufferAligned",
"(anonymous namespace)::transpose(int const*, int*, int, int)",
"void (anonymous namespace)::addition_kernel<float>(float*, float const*, float const*, int, int)",
"void (anonymous namespace)::divide_kernel<float>(float*, float const*, float const*, int, int)",
"void (anonymous namespace)::multiply_kernel<float>(float*, float const*, float const*, int, int)",
"void (anonymous namespace)::subtract_kernel<float>(float*, float const*, float const*, int, int)",
]
)
kernels = []
for row in kernel_input_data:
kernel_name = row["Kernel_Name"]
assert row["Kind"] == "KERNEL_DISPATCH"
assert int(row["Agent_Id"]) > 0
assert int(row["Queue_Id"]) > 0
assert int(row["Kernel_Id"]) > 0
assert int(row["Correlation_Id"]) > 0
assert kernel_name in valid_kernel_names
if kernel_name not in kernels:
kernels.append(kernel_name)
workgrp_size = dim3(
row["Workgroup_Size_X"], row["Workgroup_Size_Y"], row["Workgroup_Size_Z"]
)
grid_size = dim3(row["Grid_Size_X"], row["Grid_Size_Y"], row["Grid_Size_Z"])
if kernel_name == "__amd_rocclr_fillBufferAligned":
assert workgrp_size.as_tuple() > (1, 1, 1)
assert grid_size.as_tuple() > (1, 1, 1)
elif "transpose" in kernel_name:
assert workgrp_size.as_tuple() == (32, 32, 1)
assert grid_size.as_tuple() == (9920, 9920, 1)
else:
assert workgrp_size.as_tuple() == (64, 1, 1)
assert grid_size.as_tuple() == (4096, 2048, 1)
assert int(row["End_Timestamp"]) >= int(row["Start_Timestamp"])
kernels = sorted(list(set(kernels)))
assert kernels == valid_kernel_names
def test_memory_copy_trace(memory_copy_input_data):
for row in memory_copy_input_data:
assert row["Kind"] == "MEMORY_COPY"
assert row["Direction"] in ("HOST_TO_DEVICE", "DEVICE_TO_HOST")
if row["Direction"] == "HOST_TO_DEVICE":
assert int(row["Source_Agent_Id"]) == 0
elif row["Direction"] == "DEVICE_TO_HOST":
assert int(row["Destination_Agent_Id"]) == 0
assert int(row["Correlation_Id"]) > 0
assert int(row["End_Timestamp"]) >= int(row["Start_Timestamp"])
assert len(memory_copy_input_data) == 120
if __name__ == "__main__":
exit_code = pytest.main(["-x", __file__] + sys.argv[1:])
sys.exit(exit_code)
+2 -2
Просмотреть файл
@@ -40,7 +40,7 @@ set(cc-tracing-env
set_tests_properties(
rocprofv3-test-tracing-plus-cc-execute
PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT "${cc-tracing-env}"
FAIL_REGULAR_EXPRESSION "threw an exception")
FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}")
add_test(NAME rocprofv3-test-tracing-plus-cc-validate
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/validate.py
@@ -50,4 +50,4 @@ set_tests_properties(
rocprofv3-test-tracing-plus-cc-validate
PROPERTIES TIMEOUT 45 LABELS "integration-tests" DEPENDS
rocprofv3-test-tracing-plus-cc-execute FAIL_REGULAR_EXPRESSION
"threw an exception")
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
+1 -1
Просмотреть файл
@@ -34,7 +34,7 @@ def test_validate_counter_collection_plus_tracing(input_dir: pd.DataFrame):
with open(file_path, "r") as file:
df = pd.read_csv(file)
# check if either kernel-name/FUNCTION is present
assert "Kernel-Name" in df.columns or "Function" in df.columns
assert "Kernel_Name" in df.columns or "Function" in df.columns
if __name__ == "__main__":
+1 -1
Просмотреть файл
@@ -23,7 +23,7 @@ def test_hsa_api_trace(hsa_input_data):
correlation_ids = sorted(list(set(correlation_ids)))
hsa_api_calls_offset = 2 # roctxRangePush is first
num_marker_api_calls = 6 # seven marker API calls, only six entries in
num_marker_api_calls = 7 # seven marker API calls, only six entries in
# marker csv data because roctxRangePush + roctxRangePop is one entry
# all correlation ids are unique
+11 -13
Просмотреть файл
@@ -526,19 +526,16 @@ counter_collection_buffered(rocprofiler_context_id_t, /*context*/
}
void
dispatch_callback(rocprofiler_queue_id_t, /*queue_id*/
const rocprofiler_agent_t* agent,
rocprofiler_correlation_id_t, /*correlation_id*/
const hsa_kernel_dispatch_packet_t*, /*dispatch_packet*/
uint64_t, /*kernel_id*/
void* /*callback_data_args*/,
rocprofiler_profile_config_id_t* config)
dispatch_callback(rocprofiler_profile_counting_dispatch_data_t dispatch_data,
rocprofiler_profile_config_id_t* config,
rocprofiler_user_data_t* /*user_data*/,
void* /*callback_data_args*/)
{
static std::shared_mutex m_mutex = {};
static std::unordered_map<uint64_t, rocprofiler_profile_config_id_t> profile_cache = {};
auto search_cache = [&]() {
if(auto pos = profile_cache.find(agent->id.handle); pos != profile_cache.end())
if(auto pos = profile_cache.find(dispatch_data.agent_id.handle); pos != profile_cache.end())
{
*config = pos->second;
return true;
@@ -565,7 +562,7 @@ dispatch_callback(rocprofiler_queue_id_t, /*queue_id*/
// Iterate through the agents and get the counters available on that agent
ROCPROFILER_CALL(rocprofiler_iterate_agent_supported_counters(
agent->id,
dispatch_data.agent_id,
[]([[maybe_unused]] rocprofiler_agent_id_t id,
rocprofiler_counter_id_t* counters,
size_t num_counters,
@@ -600,11 +597,12 @@ dispatch_callback(rocprofiler_queue_id_t, /*queue_id*/
// Create a colleciton profile for the counters
rocprofiler_profile_config_id_t profile;
ROCPROFILER_CALL(rocprofiler_create_profile_config(
agent->id, collect_counters.data(), collect_counters.size(), &profile),
"Could not construct profile cfg");
ROCPROFILER_CALL(
rocprofiler_create_profile_config(
dispatch_data.agent_id, collect_counters.data(), collect_counters.size(), &profile),
"Could not construct profile cfg");
profile_cache.emplace(agent->id.handle, profile);
profile_cache.emplace(dispatch_data.agent_id.handle, profile);
// Return the profile to collect those counters for this dispatch
*config = profile;
}