Public C++ header files and samples updates (#819)

* Public C++ header files (source/include/rocprofiler-sdk/cxx)

* Update samples/api_buffered_tracing

- scratch memory and page migration
- README

* Update samples/api_buffered_tracing

- page migration component in sample

* Update tests/page-migration/validate.py

- fix checks for page migration operation names

* Update tests/page-migration/validate.py

- fix get_allocated_pages

* Update scratch memory and page migration validations

* Fix include/rocprofiler-sdk/cxx installation

* Rework include/rocprofiler-sdk/cxx

- Improve name_info to support const char*, string_view, string

* Update samples/api_{buffered,callback}_tracing

* External correlation ID request sample

- includes correlation ID retirement demo

* Update samples/api_buffered_tracing/README.md

* Update lib/rocprofiler-sdk/hsa/queue.cpp

- generate correlation ID for kernel launch if one doesn't exist

* Remove priority check from tool libraries (samples/tests)

- if(priority > 0) return nullptr check in rocprofiler_configure has proliferated beyond its intended use

* Apply suggestions from code review
Этот коммит содержится в:
Jonathan R. Madsen
2024-04-25 20:09:11 -05:00
коммит произвёл GitHub
родитель e2bce49655
Коммит de13d2ac5d
37 изменённых файлов: 2232 добавлений и 512 удалений
+201 -37
Просмотреть файл
@@ -30,6 +30,7 @@
#include <iostream>
#include <mutex>
#include <random>
#include <sstream>
#include <stdexcept>
#define HIP_API_CALL(CALL) \
@@ -51,7 +52,7 @@ namespace
{
using auto_lock_t = std::unique_lock<std::mutex>;
auto print_lock = std::mutex{};
size_t nthreads = 2;
size_t nthread_per_device = 2;
size_t nitr = 500;
size_t nsync = 10;
constexpr unsigned shared_mem_tile_dim = 32;
@@ -64,10 +65,19 @@ verify(int* in, int* out, int M, int N);
} // namespace
__global__ void
transpose_a(const int* in, int* out, int M, int N);
transpose(const int* in, int* out, int M, int N);
void
run(int rank, int tid, hipStream_t stream, int argc, char** argv);
run(int rank, int tid, int devid, int argc, char** argv);
void
run_transpose(int rank, int tid, hipStream_t stream, int argc, char** argv);
void
run_migrate(int rank, int tid, hipStream_t stream, int, char** argv);
void
run_scratch(int rank, int tid, hipStream_t stream, int argc, char** argv);
int
main(int argc, char** argv)
@@ -76,6 +86,8 @@ main(int argc, char** argv)
client::start(); // starts context before any API tables are available
client::identify(1);
auto* exe_name = ::basename(argv[0]);
int rank = 0;
for(int i = 1; i < argc; ++i)
{
@@ -83,47 +95,38 @@ main(int argc, char** argv)
if(_arg == "?" || _arg == "-h" || _arg == "--help")
{
fprintf(stderr,
"usage: transpose [NUM_THREADS (%zu)] [NUM_ITERATION (%zu)] "
"usage: %s [NUM_THREADS_PER_DEVICE (%zu)] [NUM_ITERATION (%zu)] "
"[SYNC_EVERY_N_ITERATIONS (%zu)]\n",
nthreads,
exe_name,
nthread_per_device,
nitr,
nsync);
exit(EXIT_SUCCESS);
}
}
if(argc > 1) nthreads = atoll(argv[1]);
if(argc > 1) nthread_per_device = atoll(argv[1]);
if(argc > 2) nitr = atoll(argv[2]);
if(argc > 3) nsync = atoll(argv[3]);
printf("[transpose] Number of threads: %zu\n", nthreads);
printf("[transpose] Number of iterations: %zu\n", nitr);
printf("[transpose] Syncing every %zu iterations\n", nsync);
// this is a temporary workaround in omnitrace when HIP + MPI is enabled
int ndevice = 0;
int devid = rank;
HIP_API_CALL(hipGetDeviceCount(&ndevice));
printf("[transpose] Number of devices found: %i\n", ndevice);
if(ndevice > 0)
auto nthreads = (ndevice * nthread_per_device);
printf("[%s] Number of devices found: %i\n", exe_name, ndevice);
printf("[%s] Number of threads (per device): %zu\n", exe_name, nthread_per_device);
printf("[%s] Number of threads (total): %zu\n", exe_name, nthreads);
printf("[%s] Number of iterations: %zu\n", exe_name, nitr);
printf("[%s] Syncing every %zu iterations\n", exe_name, nsync);
{
devid = rank % ndevice;
HIP_API_CALL(hipSetDevice(devid));
printf("[transpose] Rank %i assigned to device %i\n", rank, devid);
}
if(rank == devid && rank < ndevice)
{
std::vector<std::thread> _threads{};
std::vector<hipStream_t> _streams(nthreads);
auto _threads = std::vector<std::thread>{};
for(size_t i = 0; i < nthreads; ++i)
HIP_API_CALL(hipStreamCreate(&_streams.at(i)));
for(size_t i = 1; i < nthreads; ++i)
_threads.emplace_back(run, rank, i, _streams.at(i), argc, argv);
run(rank, 0, _streams.at(0), argc, argv);
_threads.emplace_back(run, rank, i, i % ndevice, argc, argv);
for(auto& itr : _threads)
itr.join();
for(size_t i = 0; i < nthreads; ++i)
HIP_API_CALL(hipStreamDestroy(_streams.at(i)));
}
HIP_API_CALL(hipDeviceSynchronize());
HIP_API_CALL(hipDeviceReset());
@@ -134,7 +137,7 @@ main(int argc, char** argv)
}
__global__ void
transpose_a(const int* in, int* out, int M, int N)
transpose(const int* in, int* out, int M, int N)
{
__shared__ int tile[shared_mem_tile_dim][shared_mem_tile_dim];
@@ -145,17 +148,91 @@ transpose_a(const int* in, int* out, int M, int N)
out[idx] = tile[threadIdx.x][threadIdx.y];
}
template <typename Tp>
__global__ void
test_page_migrate(Tp* data, Tp val)
{
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
data[idx] += val;
}
__global__ void
test_kern_large(uint64_t* output)
{
uint64_t result = 0;
int test[4000];
memset(test, 5, 4000);
for(int& i : test)
{
i = i + 7;
*output += i;
result += i;
}
*output ^= result;
*output ^= result;
}
__global__ void
test_kern_medium(uint64_t* output)
{
uint64_t result = 0;
int test[175];
memset(test, 5, 175);
for(int& i : test)
{
i = i + 7;
*output += i;
result += i;
}
*output ^= result;
*output ^= result;
}
__global__ void
test_kern_small(uint64_t* output)
{
uint64_t result = 0;
int test[2];
for(int& i : test)
{
i = i + 7;
*output += i;
result += i;
}
*output ^= result;
*output ^= result;
}
void
run(int rank, int tid, hipStream_t stream, int argc, char** argv)
run(int rank, int tid, int devid, int argc, char** argv)
{
client::identify(tid + 1);
auto* stream = hipStream_t{};
HIP_API_CALL(hipSetDevice(devid));
HIP_API_CALL(hipStreamCreate(&stream));
run_migrate(rank, tid, stream, argc, argv);
run_scratch(rank, tid, stream, argc, argv);
run_transpose(rank, tid, stream, argc, argv);
HIP_API_CALL(hipStreamSynchronize(stream));
HIP_API_CALL(hipStreamDestroy(stream));
}
void
run_transpose(int rank, int tid, hipStream_t stream, int argc, char** argv)
{
auto* exe_name = ::basename(argv[0]);
unsigned int M = 4960 * 2;
unsigned int N = 4960 * 2;
if(argc > 2) nitr = atoll(argv[2]);
if(argc > 3) nsync = atoll(argv[3]);
auto_lock_t _lk{print_lock};
std::cout << "[transpose][" << rank << "][" << tid << "] M: " << M << " N: " << N << std::endl;
std::cout << "[" << exe_name << "][transpose][" << rank << "][" << tid << "] M: " << M
<< " N: " << N << std::endl;
_lk.unlock();
std::default_random_engine _engine{std::random_device{}() * (rank + 1) * (tid + 1)};
@@ -180,10 +257,11 @@ run(int rank, int tid, hipStream_t stream, int argc, char** argv)
HIP_API_CALL(hipStreamSynchronize(stream));
dim3 grid(M / 32, N / 32, 1);
dim3 block(32, 32, 1); // transpose_a
dim3 block(32, 32, 1); // transpose
print_lock.lock();
printf("[transpose][%i][%i] grid=(%i,%i,%i), block=(%i,%i,%i)\n",
printf("[%s][transpose][%i][%i] grid=(%i,%i,%i), block=(%i,%i,%i)\n",
exe_name,
rank,
tid,
grid.x,
@@ -197,7 +275,7 @@ run(int rank, int tid, hipStream_t stream, int argc, char** argv)
auto t1 = std::chrono::high_resolution_clock::now();
for(size_t i = 0; i < nitr; ++i)
{
transpose_a<<<grid, block, 0, stream>>>(in, out, M, N);
transpose<<<grid, block, 0, stream>>>(in, out, M, N);
check_hip_error();
if(i % nsync == (nsync - 1)) HIP_API_CALL(hipStreamSynchronize(stream));
}
@@ -208,9 +286,9 @@ run(int rank, int tid, hipStream_t stream, int argc, char** argv)
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
std::cout << "[" << exe_name << "][transpose][" << rank << "][" << tid
<< "] Runtime of transpose is " << time << " sec\n";
std::cout << "[" << exe_name << "][transpose][" << rank << "][" << tid
<< "] The average performance of transpose is " << GB / time << " GBytes/sec"
<< std::endl;
print_lock.unlock();
@@ -227,6 +305,92 @@ run(int rank, int tid, hipStream_t stream, int argc, char** argv)
delete[] out_matrix;
}
void
run_scratch(int rank, int tid, hipStream_t stream, int, char** argv)
{
auto t1 = std::chrono::high_resolution_clock::now();
HIP_API_CALL(hipStreamSynchronize(stream));
const auto* exe_name = ::basename(argv[0]);
uint64_t* data_ptr = nullptr;
HIP_API_CALL(hipHostMalloc(&data_ptr, sizeof(uint64_t), 0));
*data_ptr = 0;
test_kern_small<<<1000, 1, 0, stream>>>(data_ptr);
test_kern_medium<<<1000, 1, 0, stream>>>(data_ptr);
test_kern_small<<<1000, 1, 0, stream>>>(data_ptr);
test_kern_large<<<1100, 1, 0, stream>>>(data_ptr);
HIP_API_CALL(hipStreamSynchronize(stream));
test_kern_small<<<1000, 1, 0, stream>>>(data_ptr);
HIP_API_CALL(hipStreamSynchronize(stream));
test_kern_medium<<<1000, 1, 0, stream>>>(data_ptr);
HIP_API_CALL(hipStreamSynchronize(stream));
test_kern_small<<<1000, 1, 0, stream>>>(data_ptr);
HIP_API_CALL(hipStreamSynchronize(stream));
test_kern_large<<<1100, 1, 0, stream>>>(data_ptr);
HIP_API_CALL(hipStreamSynchronize(stream));
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 << "[" << exe_name << "][scratch][" << rank << "][" << tid
<< "] Runtime of scratch is " << time << " sec\n";
print_lock.unlock();
}
void
run_migrate(int rank, int tid, hipStream_t stream, int, char** argv)
{
using data_type = uint64_t;
constexpr data_type init_v = 1;
constexpr data_type incr_v = 1;
auto t1 = std::chrono::high_resolution_clock::now();
HIP_API_CALL(hipStreamSynchronize(stream));
const auto* exe_name = ::basename(argv[0]);
auto page_data = std::vector<data_type>(1024, 0);
HIP_API_CALL(hipHostRegister(
page_data.data(), page_data.size() * sizeof(data_type), hipHostRegisterDefault));
for(auto& itr : page_data)
itr = init_v;
test_page_migrate<<<1, 1024, 0, stream>>>(page_data.data(), incr_v);
HIP_API_CALL(hipStreamSynchronize(stream));
for(auto& itr : page_data)
{
auto diff = (itr - incr_v);
if(diff != init_v)
{
auto msg = std::stringstream{};
msg << "invalid diff: " << diff << ". expected: " << init_v;
throw std::runtime_error{msg.str()};
}
}
HIP_API_CALL(hipHostUnregister(page_data.data()));
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 << "[" << exe_name << "][migrate][" << rank << "][" << tid
<< "] Runtime of migrate is " << time << " sec\n";
print_lock.unlock();
}
namespace
{
void