Files
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

167 lines
6.9 KiB
C++

/*
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
*
* SPDX-License-Identifier: MIT
*/
#include "rockernel.hpp"
#include <algorithm>
namespace amd::roc {
bool Kernel::init() { return GetAttrCodePropMetadata(); }
bool Kernel::postLoad() {
// Set the kernel symbol name and size/alignment based on the kernel metadata
// NOTE: kernel name is used to get the kernel code handle in V2,
// but kernel symbol name is used in V3
if (codeObjectVer() == 2) {
symbolName_ = name();
}
kernargSegmentAlignment_ = amd::alignUp(std::max(kernargSegmentAlignment_, 128u),
device().info().globalMemCacheLineSize_);
// Set the workgroup information for the kernel
workGroupInfo_.availableLDSSize_ = device().info().localMemSizePerCU_;
assert(workGroupInfo_.availableLDSSize_ > 0);
// Get the kernel code handle
hsa_status_t hsaStatus;
hsa_executable_symbol_t symbol;
hsa_agent_t agent = program()->rocDevice().getBackendDevice();
hsaStatus = Hsa::executable_get_symbol_by_name(program()->hsaExecutable(), symbolName().c_str(),
&agent, &symbol);
if (hsaStatus != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
"Cannot Get Symbol : %s, failed with hsa_status: %d \n", symbolName().c_str(),
hsaStatus);
return false;
}
hsaStatus = Hsa::executable_symbol_get_info(symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT,
&kernelCodeHandle_);
if (hsaStatus != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
" Cannot Get Symbol Info: %s, failed with hsa_status: %d \n ",
symbolName().c_str(), hsaStatus);
return false;
}
// Resolve the metadata kernel descriptor for prefetching at load time,
// so dispatch doesn't need to call loaderQueryHostAddress per packet.
const void* host_address = nullptr;
Device::loaderQueryHostAddress(reinterpret_cast<void*>(kernelCodeHandle_), &host_address);
if (host_address != nullptr) {
constexpr size_t KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET = 16;
auto* descriptor = reinterpret_cast<const hsa_amd_metadata_kernel_descriptor_t*>(
reinterpret_cast<const uint8_t*>(host_address) + KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET);
metadataKernelDescriptor_ = descriptor;
metadata_preload_length_ = descriptor->kernarg_preload.length;
metadata_preload_offset_ = descriptor->kernarg_preload.offset;
}
hsaStatus = Hsa::executable_symbol_get_info(
symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_DYNAMIC_CALLSTACK, &kernelHasDynamicCallStack_);
if (hsaStatus != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
" Cannot Get Dynamic callstack info, failed with hsa_status: %d \n ",
hsaStatus);
return false;
}
if (!RuntimeHandle().empty()) {
hsa_executable_symbol_t kernelSymbol;
int variable_size;
uint64_t variable_address;
// Only kernels that could be enqueued by another kernel has the RuntimeHandle metadata. The
// RuntimeHandle metadata is a string that represents a variable from which the library code can
// retrieve the kernel code object handle of such a kernel. The address of the variable and the
// kernel code object handle are known only after the hsa executable is loaded. The below code
// copies the kernel code object handle to the address of the variable.
hsaStatus = Hsa::executable_get_symbol_by_name(program()->hsaExecutable(),
RuntimeHandle().c_str(), &agent, &kernelSymbol);
if (hsaStatus != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
"Cannot get Kernel Symbol by name: %s, failed with hsa_status: %d \n",
RuntimeHandle().c_str(), hsaStatus);
return false;
}
hsaStatus = Hsa::executable_symbol_get_info(
kernelSymbol, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_SIZE, &variable_size);
if (hsaStatus != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
"[ROC][Kernel] Cannot get Kernel Symbol Info, failed with hsa_status: %d \n", hsaStatus);
return false;
}
hsaStatus = Hsa::executable_symbol_get_info(
kernelSymbol, HSA_EXECUTABLE_SYMBOL_INFO_VARIABLE_ADDRESS, &variable_address);
if (hsaStatus != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
"[ROC][Kernel] Cannot get Kernel Address, failed with hsa_status: %d \n",
hsaStatus);
return false;
}
const struct RuntimeHandle runtime_handle = {
kernelCodeHandle_, WorkitemPrivateSegmentByteSize(), WorkgroupGroupSegmentByteSize()};
hsaStatus =
Hsa::memory_copy(reinterpret_cast<void*>(variable_address), &runtime_handle, variable_size);
if (hsaStatus != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
"[ROC][Kernel] HSA Memory copy failed, failed with hsa_status: %d \n",
hsaStatus);
return false;
}
}
// This can be set in code object and the value might be different than what HSA reports
// For example on Navi GPUs someone using -mwavefrontsize64
// We set the value to HSA if the value is uninitialized
uint32_t wavefront_size = workGroupInfo_.wavefrontPerSIMD_;
if (wavefront_size == 0 &&
Hsa::agent_get_info(program()->rocDevice().getBackendDevice(), HSA_AGENT_INFO_WAVEFRONT_SIZE,
&wavefront_size) != HSA_STATUS_SUCCESS) {
ClPrint(amd::LOG_DETAIL_DEBUG, amd::LOG_KERN,
"[ROC][Kernel] Cannot get Wavefront Size, failed with hsa_status: %d \n",
hsaStatus);
return false;
}
assert(wavefront_size > 0);
workGroupInfo_.availableVGPRs_ = device().info().availableVGPRs_;
workGroupInfo_.availableSGPRs_ = device().info().availableSGPRs_;
workGroupInfo_.privateMemSize_ = workitemPrivateSegmentByteSize_;
workGroupInfo_.localMemSize_ = workgroupGroupSegmentByteSize_;
workGroupInfo_.usedLDSSize_ = workgroupGroupSegmentByteSize_;
workGroupInfo_.preferredSizeMultiple_ = wavefront_size;
workGroupInfo_.usedStackSize_ = kernelHasDynamicCallStack_;
workGroupInfo_.wavefrontPerSIMD_ =
program()->rocDevice().info().maxWorkItemSizes_[0] / wavefront_size;
workGroupInfo_.constMemSize_ = 0;
workGroupInfo_.maxDynamicSharedSizeBytes_ =
static_cast<int>(workGroupInfo_.availableLDSSize_ - workGroupInfo_.localMemSize_);
if (workGroupInfo_.size_ == 0) {
return false;
}
// handle the printf metadata if any
std::vector<std::string> printfStr;
if (!GetPrintfStr(&printfStr)) {
return false;
}
if (!printfStr.empty()) {
InitPrintf(printfStr);
}
// Add kernel to the map of all kernels on the device
program()->rocDevice().AddKernel(*this);
return true;
}
} // namespace amd::roc