CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
418 lines
12 KiB
C++
418 lines
12 KiB
C++
/*
|
|
* Copyright © Advanced Micro Devices, Inc., or its affiliates.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
|
|
#include "suites/performance/agent_preload.h"
|
|
#include "common/base_rocr_utils.h"
|
|
#include "common/helper_funcs.h"
|
|
#include "common/hsatimer.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
// Find a global memory pool
|
|
static hsa_status_t FindGlobalPool(hsa_amd_memory_pool_t pool, void* data) {
|
|
hsa_amd_segment_t segment;
|
|
hsa_amd_memory_pool_get_info(pool, HSA_AMD_MEMORY_POOL_INFO_SEGMENT, &segment);
|
|
|
|
if (segment != HSA_AMD_SEGMENT_GLOBAL) {
|
|
return HSA_STATUS_SUCCESS;
|
|
}
|
|
|
|
bool alloc_allowed = false;
|
|
hsa_amd_memory_pool_get_info(pool,
|
|
HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED, &alloc_allowed);
|
|
|
|
if (!alloc_allowed) {
|
|
return HSA_STATUS_SUCCESS;
|
|
}
|
|
|
|
hsa_amd_memory_pool_t* out_pool = static_cast<hsa_amd_memory_pool_t*>(data);
|
|
*out_pool = pool;
|
|
return HSA_STATUS_INFO_BREAK;
|
|
}
|
|
|
|
AgentPreloadTest::AgentPreloadTest() : TestBase() {
|
|
set_num_iteration(10);
|
|
set_title("Agent Preload Latency Test");
|
|
set_description("This test measures the latency reduction achieved by using "
|
|
"hsa_amd_agent_preload() before calling "
|
|
"hsa_amd_profiling_async_copy_enable(). The preload API warms"
|
|
"up the clock counter cache to avoid first-call latency.");
|
|
|
|
latency_without_preload_us_ = 0.0;
|
|
latency_with_preload_us_ = 0.0;
|
|
latency_improvement_us_ = 0.0;
|
|
blit_latency_without_preload_us_ = 0.0;
|
|
blit_latency_with_preload_us_ = 0.0;
|
|
blit_latency_improvement_us_ = 0.0;
|
|
}
|
|
|
|
AgentPreloadTest::~AgentPreloadTest() {
|
|
}
|
|
|
|
void AgentPreloadTest::SetUp() {
|
|
hsa_status_t err;
|
|
TestBase::SetUp();
|
|
if (test_skipped_) return;
|
|
|
|
err = hsa_iterate_agents(rocrtst::IterateGPUAgents, &gpu_agents_);
|
|
ASSERT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
err = hsa_iterate_agents(rocrtst::IterateCPUAgents, &cpu_agents_);
|
|
ASSERT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
if (gpu_agents_.empty()) {
|
|
std::cout << "No GPU agents found. Test will be skipped." << std::endl;
|
|
}
|
|
}
|
|
|
|
void AgentPreloadTest::Run() {
|
|
if (!rocrtst::CheckProfile(this)) {
|
|
return;
|
|
}
|
|
|
|
TestBase::Run();
|
|
|
|
if (gpu_agents_.empty()) {
|
|
std::cout << "No GPU agents available. Skipping test." << std::endl;
|
|
return;
|
|
}
|
|
|
|
latency_without_preload_us_ = MeasureProfilingEnableLatencyWithoutPreload();
|
|
latency_with_preload_us_ = MeasureProfilingEnableLatencyWithPreload();
|
|
latency_improvement_us_ = latency_without_preload_us_ - latency_with_preload_us_;
|
|
EXPECT_GT(latency_improvement_us_, 0.0);
|
|
|
|
blit_latency_without_preload_us_ = MeasureFirstAsyncCopyLatencyWithoutPreload();
|
|
blit_latency_with_preload_us_ = MeasureFirstAsyncCopyLatencyWithPreload();
|
|
blit_latency_improvement_us_ = blit_latency_without_preload_us_ - blit_latency_with_preload_us_;
|
|
EXPECT_GT(blit_latency_improvement_us_, 0.0);
|
|
}
|
|
|
|
double AgentPreloadTest::MeasureProfilingEnableLatencyWithoutPreload() {
|
|
hsa_status_t err;
|
|
|
|
err = hsa_shut_down();
|
|
EXPECT_TRUE(err == HSA_STATUS_SUCCESS ||
|
|
err == HSA_STATUS_ERROR_NOT_INITIALIZED);
|
|
|
|
err = hsa_init();
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
std::vector<hsa_agent_t> gpus;
|
|
std::vector<hsa_agent_t> cpus;
|
|
err = hsa_iterate_agents(rocrtst::IterateGPUAgents, &gpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
err = hsa_iterate_agents(rocrtst::IterateCPUAgents, &cpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
if (gpus.empty()) {
|
|
return 0.0;
|
|
}
|
|
|
|
// Measure time for hsa_amd_profiling_async_copy_enable without preload
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
err = hsa_amd_profiling_async_copy_enable(true);
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
err = hsa_amd_profiling_async_copy_enable(false);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
|
|
double latency_us = duration.count() / 1000.0;
|
|
|
|
if (verbosity() > 0) {
|
|
std::cout << " Profiling enable latency WITHOUT preload: "
|
|
<< std::fixed << std::setprecision(2) << latency_us << " us" << std::endl;
|
|
}
|
|
|
|
return latency_us;
|
|
}
|
|
|
|
double AgentPreloadTest::MeasureProfilingEnableLatencyWithPreload() {
|
|
hsa_status_t err;
|
|
|
|
err = hsa_shut_down();
|
|
EXPECT_TRUE(err == HSA_STATUS_SUCCESS ||
|
|
err == HSA_STATUS_ERROR_NOT_INITIALIZED);
|
|
|
|
err = hsa_init();
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
std::vector<hsa_agent_t> gpus;
|
|
std::vector<hsa_agent_t> cpus;
|
|
err = hsa_iterate_agents(rocrtst::IterateGPUAgents, &gpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
err = hsa_iterate_agents(rocrtst::IterateCPUAgents, &cpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
if (gpus.empty()) {
|
|
return 0.0;
|
|
}
|
|
|
|
// Preload clock sync for all GPU agents
|
|
for (const auto& gpu : gpus) {
|
|
err = hsa_amd_agent_preload(gpu, HSA_AMD_AGENT_PRELOAD_SKIP_BLITS);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
}
|
|
|
|
// Measure time for hsa_amd_profiling_async_copy_enable with preload
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
err = hsa_amd_profiling_async_copy_enable(true);
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
err = hsa_amd_profiling_async_copy_enable(false);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
|
|
double latency_us = duration.count() / 1000.0;
|
|
|
|
if (verbosity() > 0) {
|
|
std::cout << " Profiling enable latency WITH preload: "
|
|
<< std::fixed << std::setprecision(2) << latency_us << " us" << std::endl;
|
|
}
|
|
|
|
return latency_us;
|
|
}
|
|
|
|
double AgentPreloadTest::MeasureFirstAsyncCopyLatencyWithoutPreload() {
|
|
hsa_status_t err;
|
|
err = hsa_shut_down();
|
|
EXPECT_TRUE(err == HSA_STATUS_SUCCESS ||
|
|
err == HSA_STATUS_ERROR_NOT_INITIALIZED);
|
|
|
|
err = hsa_init();
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
std::vector<hsa_agent_t> gpus;
|
|
std::vector<hsa_agent_t> cpus;
|
|
err = hsa_iterate_agents(rocrtst::IterateGPUAgents, &gpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
err = hsa_iterate_agents(rocrtst::IterateCPUAgents, &cpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
if (gpus.empty() || cpus.empty()) {
|
|
return 0.0;
|
|
}
|
|
|
|
hsa_amd_memory_pool_t gpu_pool;
|
|
err = hsa_amd_agent_iterate_memory_pools(gpus[0], FindGlobalPool, &gpu_pool);
|
|
if (err != HSA_STATUS_INFO_BREAK) {
|
|
return 0.0;
|
|
}
|
|
|
|
hsa_amd_memory_pool_t cpu_pool;
|
|
err = hsa_amd_agent_iterate_memory_pools(cpus[0], FindGlobalPool, &cpu_pool);
|
|
if (err != HSA_STATUS_INFO_BREAK) {
|
|
return 0.0;
|
|
}
|
|
|
|
const size_t size = 4096;
|
|
void* src_ptr = nullptr;
|
|
void* dst_ptr = nullptr;
|
|
|
|
err = hsa_amd_memory_pool_allocate(cpu_pool, size, 0, &src_ptr);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
return 0.0;
|
|
}
|
|
|
|
err = hsa_amd_memory_pool_allocate(gpu_pool, size, 0, &dst_ptr);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
err = hsa_amd_agents_allow_access(1, &gpus[0], nullptr, src_ptr);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
hsa_signal_t signal;
|
|
err = hsa_signal_create(1, 0, nullptr, &signal);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
// Measure first async copy without preloading blits
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
err = hsa_amd_memory_async_copy(dst_ptr, gpus[0], src_ptr, cpus[0], size, 0,
|
|
nullptr, signal);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_signal_destroy(signal);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
hsa_signal_value_t signal_value =
|
|
hsa_signal_wait_scacquire(signal, HSA_SIGNAL_CONDITION_LT,
|
|
1, UINT64_MAX, HSA_WAIT_STATE_BLOCKED);
|
|
if (signal_value != 0) {
|
|
EXPECT_EQ(signal_value, 0);
|
|
hsa_signal_destroy(signal);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
hsa_signal_destroy(signal);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
|
|
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
|
|
double latency_us = duration.count() / 1000.0;
|
|
|
|
if (verbosity() > 0) {
|
|
std::cout << " First async copy latency WITHOUT blit preload: "
|
|
<< std::fixed << std::setprecision(2) << latency_us << " us" << std::endl;
|
|
}
|
|
|
|
return latency_us;
|
|
}
|
|
|
|
double AgentPreloadTest::MeasureFirstAsyncCopyLatencyWithPreload() {
|
|
hsa_status_t err;
|
|
err = hsa_shut_down();
|
|
EXPECT_TRUE(err == HSA_STATUS_SUCCESS ||
|
|
err == HSA_STATUS_ERROR_NOT_INITIALIZED);
|
|
|
|
err = hsa_init();
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
std::vector<hsa_agent_t> gpus;
|
|
std::vector<hsa_agent_t> cpus;
|
|
err = hsa_iterate_agents(rocrtst::IterateGPUAgents, &gpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
err = hsa_iterate_agents(rocrtst::IterateCPUAgents, &cpus);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
|
|
if (gpus.empty() || cpus.empty()) {
|
|
return 0.0;
|
|
}
|
|
|
|
// Preload blits
|
|
for (const auto& gpu : gpus) {
|
|
err = hsa_amd_agent_preload(gpu, HSA_AMD_AGENT_PRELOAD_SKIP_CLOCK_SYNC);
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
}
|
|
|
|
hsa_amd_memory_pool_t gpu_pool;
|
|
err = hsa_amd_agent_iterate_memory_pools(gpus[0], FindGlobalPool, &gpu_pool);
|
|
if (err != HSA_STATUS_INFO_BREAK) {
|
|
return 0.0;
|
|
}
|
|
|
|
hsa_amd_memory_pool_t cpu_pool;
|
|
err = hsa_amd_agent_iterate_memory_pools(cpus[0], FindGlobalPool, &cpu_pool);
|
|
if (err != HSA_STATUS_INFO_BREAK) {
|
|
return 0.0;
|
|
}
|
|
|
|
const size_t size = 4096;
|
|
void* src_ptr = nullptr;
|
|
void* dst_ptr = nullptr;
|
|
|
|
err = hsa_amd_memory_pool_allocate(cpu_pool, size, 0, &src_ptr);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
return 0.0;
|
|
}
|
|
|
|
err = hsa_amd_memory_pool_allocate(gpu_pool, size, 0, &dst_ptr);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
err = hsa_amd_agents_allow_access(1, &gpus[0], nullptr, src_ptr);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
hsa_signal_t signal;
|
|
err = hsa_signal_create(1, 0, nullptr, &signal);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
// Measure first async copy with blits preloaded
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
err = hsa_amd_memory_async_copy(dst_ptr, gpus[0], src_ptr, cpus[0], size, 0, nullptr, signal);
|
|
if (err != HSA_STATUS_SUCCESS) {
|
|
EXPECT_EQ(err, HSA_STATUS_SUCCESS);
|
|
hsa_signal_destroy(signal);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
|
|
hsa_signal_value_t signal_value =
|
|
hsa_signal_wait_scacquire(signal, HSA_SIGNAL_CONDITION_LT,
|
|
1, UINT64_MAX, HSA_WAIT_STATE_BLOCKED);
|
|
if (signal_value != 0) {
|
|
EXPECT_EQ(signal_value, 0);
|
|
hsa_signal_destroy(signal);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
return 0.0;
|
|
}
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
hsa_signal_destroy(signal);
|
|
hsa_amd_memory_pool_free(src_ptr);
|
|
hsa_amd_memory_pool_free(dst_ptr);
|
|
|
|
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
|
|
double latency_us = duration.count() / 1000.0;
|
|
|
|
if (verbosity() > 0) {
|
|
std::cout << " First async copy latency WITH blit preload: "
|
|
<< std::fixed << std::setprecision(2) << latency_us << " us" << std::endl;
|
|
}
|
|
|
|
return latency_us;
|
|
}
|
|
|
|
void AgentPreloadTest::DisplayTestInfo(void) {
|
|
TestBase::DisplayTestInfo();
|
|
}
|
|
|
|
void AgentPreloadTest::DisplayResults(void) const {
|
|
if (!rocrtst::CheckProfile(this)) {
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void AgentPreloadTest::Close() {
|
|
TestBase::Close();
|
|
}
|