diff --git a/projects/clr/rocclr/runtime/device/pal/palkernel.cpp b/projects/clr/rocclr/runtime/device/pal/palkernel.cpp index fbfe429231..2b2df120ed 100644 --- a/projects/clr/rocclr/runtime/device/pal/palkernel.cpp +++ b/projects/clr/rocclr/runtime/device/pal/palkernel.cpp @@ -29,13 +29,15 @@ bool HSAILKernel::aqlCreateHWInfo(amd::hsa::loader::Symbol* sym) { return false; } - amd_kernel_code_t* akc = - reinterpret_cast(prog().findHostKernelAddress(code_)); - cpuAqlCode_ = akc; if (!sym->GetInfo(HSA_EXT_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT_SIZE, - reinterpret_cast(&codeSize_))) { + reinterpret_cast(&codeSize_))) { return false; } + + amd_kernel_code_t* akc = &akc_; + // Copy codeobject of this kernel from the program CPU segment + memcpy(akc, reinterpret_cast(prog().findHostKernelAddress(code_)), sizeof(amd_kernel_code_t)); + size_t akc_align = 0; if (!sym->GetInfo(HSA_EXT_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT_ALIGN, reinterpret_cast(&akc_align))) { @@ -74,7 +76,8 @@ HSAILKernel::HSAILKernel(std::string name, HSAILProgram* prog, std::string compi prog_(*prog), index_(0), code_(0), - codeSize_(0) { + codeSize_(0) + { flags_.hsa_ = true; } @@ -359,7 +362,7 @@ hsa_kernel_dispatch_packet_t* HSAILKernel::loadArguments( hsaDisp->completion_signal.handle = 0; memcpy(aqlArgBuf + argsBufferSize(), hsaDisp, sizeof(hsa_kernel_dispatch_packet_t)); - if (AMD_HSA_BITS_GET(cpuAqlCode_->kernel_code_properties, + if (AMD_HSA_BITS_GET(akc_.kernel_code_properties, AMD_KERNEL_CODE_PROPERTIES_ENABLE_SGPR_QUEUE_PTR)) { gpu.addVmMemory(gpu.hsaQueueMem()); } diff --git a/projects/clr/rocclr/runtime/device/pal/palkernel.hpp b/projects/clr/rocclr/runtime/device/pal/palkernel.hpp index c7477697c0..d94ae849d3 100644 --- a/projects/clr/rocclr/runtime/device/pal/palkernel.hpp +++ b/projects/clr/rocclr/runtime/device/pal/palkernel.hpp @@ -66,10 +66,10 @@ class HSAILKernel : public device::Kernel { const HSAILProgram& prog() const; //! Returns LDS size used in this kernel - uint32_t ldsSize() const { return cpuAqlCode_->workgroup_group_segment_byte_size; } + uint32_t ldsSize() const { return akc_.workgroup_group_segment_byte_size; } //! Returns pointer on CPU to AQL code info - const amd_kernel_code_t* cpuAqlCode() const { return cpuAqlCode_; } + const amd_kernel_code_t* cpuAqlCode() const { return &akc_; } //! Returns memory object with AQL code uint64_t gpuAqlCode() const { return code_; } @@ -78,10 +78,10 @@ class HSAILKernel : public device::Kernel { size_t aqlCodeSize() const { return codeSize_; } //! Returns the size of argument buffer - size_t argsBufferSize() const { return cpuAqlCode_->kernarg_segment_byte_size; } + size_t argsBufferSize() const { return akc_.kernarg_segment_byte_size; } //! Returns spill reg size per workitem - int spillSegSize() const { return amd::alignUp(cpuAqlCode_->workitem_private_segment_byte_size, sizeof(uint32_t)); } + int spillSegSize() const { return amd::alignUp(akc_.workitem_private_segment_byte_size, sizeof(uint32_t)); } //! Returns AQL packet in CPU memory //! if the kernel arguments were successfully loaded, otherwise NULL @@ -109,13 +109,13 @@ class HSAILKernel : public device::Kernel { //! Creates AQL kernel HW info bool aqlCreateHWInfo(amd::hsa::loader::Symbol* sym); - std::string compileOptions_; //!< compile used for finalizing this kernel - amd_kernel_code_t* cpuAqlCode_; //!< AQL kernel code on CPU - const HSAILProgram& prog_; //!< Reference to the parent program - uint index_; //!< Kernel index in the program + std::string compileOptions_; //!< compile used for finalizing this kernel + amd_kernel_code_t akc_; //!< AQL kernel code on CPU + const HSAILProgram& prog_; //!< Reference to the parent program + uint index_; //!< Kernel index in the program - uint64_t code_; //!< GPU memory pointer to the kernel - size_t codeSize_; //!< Size of ISA code + uint64_t code_; //!< GPU memory pointer to the kernel + size_t codeSize_; //!< Size of ISA code }; #if defined(WITH_LIGHTNING_COMPILER) diff --git a/projects/clr/rocclr/runtime/device/pal/palprogram.cpp b/projects/clr/rocclr/runtime/device/pal/palprogram.cpp index b71f6de041..0417ba3279 100644 --- a/projects/clr/rocclr/runtime/device/pal/palprogram.cpp +++ b/projects/clr/rocclr/runtime/device/pal/palprogram.cpp @@ -28,13 +28,22 @@ namespace pal { -Segment::Segment() : gpuAccess_(nullptr), cpuAccess_(nullptr) {} +Segment::Segment() : gpuAccess_(nullptr), cpuAccess_(nullptr), cpuMem_(nullptr) {} Segment::~Segment() { delete gpuAccess_; + DestroyCpuAccess(); +} + +void Segment::DestroyCpuAccess() { if (cpuAccess_ != nullptr) { cpuAccess_->unmap(nullptr); delete cpuAccess_; + cpuAccess_ = nullptr; + } + if (cpuMem_ != nullptr) { + delete[] cpuMem_; + cpuMem_ = nullptr; } } @@ -48,13 +57,18 @@ bool Segment::alloc(HSAILProgram& prog, amdgpu_hsa_elf_segment_t segment, size_t return false; } if (segment == AMDGPU_HSA_SEGMENT_CODE_AGENT) { + void* ptr = nullptr; cpuAccess_ = new pal::Memory(prog.dev(), amd::alignUp(size, align)); if ((cpuAccess_ == nullptr) || !cpuAccess_->create(pal::Resource::Remote)) { delete cpuAccess_; cpuAccess_ = nullptr; - return false; + ptr = cpuMem_ = reinterpret_cast
(new char[amd::alignUp(size, align)]); + if (cpuMem_ == nullptr) { + return false; + } + } else { + ptr = cpuAccess_->map(nullptr, 0); } - void* ptr = cpuAccess_->map(nullptr, 0); if (zero) { memset(ptr, 0, size); } @@ -75,7 +89,7 @@ bool Segment::alloc(HSAILProgram& prog, amdgpu_hsa_elf_segment_t segment, size_t prog.setGlobalVariableTotalSize(prog.globalVariableTotalSize() + size); break; case AMDGPU_HSA_SEGMENT_CODE_AGENT: - prog.setCodeObjects(gpuAccess_, cpuAccess_->data()); + prog.setCodeObjects(this, gpuAccess_, reinterpret_cast
(cpuAddress(0))); break; default: break; @@ -87,6 +101,9 @@ void Segment::copy(size_t offset, const void* src, size_t size) { if (cpuAccess_ != nullptr) { amd::Os::fastMemcpy(cpuAddress(offset), src, size); } else { + if (cpuMem_ != nullptr) { + amd::Os::fastMemcpy(cpuAddress(offset), src, size); + } amd::ScopedLock k(gpuAccess_->dev().xferMgr().lockXfer()); VirtualGPU& gpu = *gpuAccess_->dev().xferQueue(); Memory& xferBuf = gpu.xferWrite().Acquire(size); @@ -124,7 +141,7 @@ HSAILProgram::HSAILProgram(Device& device) rawBinary_(nullptr), kernels_(nullptr), codeSegGpu_(nullptr), - codeSegCpu_(nullptr), + codeSegment_(nullptr), maxScratchRegs_(0), flags_(0), executable_(nullptr), @@ -145,7 +162,7 @@ HSAILProgram::HSAILProgram(NullDevice& device) rawBinary_(nullptr), kernels_(nullptr), codeSegGpu_(nullptr), - codeSegCpu_(nullptr), + codeSegment_(nullptr), maxScratchRegs_(0), flags_(0), executable_(nullptr), @@ -695,6 +712,9 @@ bool HSAILProgram::linkImpl(amd::option::Options* options) { return false; } } + + DestroySegmentCpuAccess(); + // Save the binary in the interface class saveBinaryAndSetType(TYPE_EXECUTABLE); buildLog_ += aclGetCompilerLog(dev().compiler()); @@ -1426,6 +1446,8 @@ bool LightningProgram::setKernels(amd::option::Options* options, void* binary, s } size_t progvarsTotalSize = 0; + size_t dynamicSize = 0; + size_t progvarsWriteSize = 0; // Begin the Elf image from memory Elf* e = elf_memory((char*)binary, size, NULL); @@ -1481,8 +1503,16 @@ bool LightningProgram::setKernels(amd::option::Options* options, void* binary, s } } // Accumulate the size of R & !X loadable segments - else if (pHdr.p_type == PT_LOAD && (pHdr.p_flags & PF_R) && !(pHdr.p_flags & PF_X)) { - progvarsTotalSize += pHdr.p_memsz; + else if (pHdr.p_type == PT_LOAD && !(pHdr.p_flags & PF_X)) { + if (pHdr.p_flags & PF_R) { + progvarsTotalSize += pHdr.p_memsz; + } + if (pHdr.p_flags & PF_W) { + progvarsWriteSize += pHdr.p_memsz; + } + } + else if (pHdr.p_type == PT_DYNAMIC) { + dynamicSize += pHdr.p_memsz; } } @@ -1495,8 +1525,8 @@ bool LightningProgram::setKernels(amd::option::Options* options, void* binary, s return false; } - // note: The global variable size is updated in the context loader - // setGlobalVariableTotalSize(progvarsTotalSize); + progvarsTotalSize -= dynamicSize; + setGlobalVariableTotalSize(progvarsTotalSize); // Get the list of kernels std::vector kernelNameList; @@ -1506,7 +1536,7 @@ bool LightningProgram::setKernels(amd::option::Options* options, void* binary, s return false; } - for (auto& kernelName : kernelNameList) { + for (const auto& kernelName : kernelNameList) { auto kernel = new LightningKernel(kernelName, this, options->origOptionStr + ProcessOptions(options)); @@ -1538,6 +1568,8 @@ bool LightningProgram::setKernels(amd::option::Options* options, void* binary, s return false; } + DestroySegmentCpuAccess(); + // Save the binary and type clBinary()->saveBIFBinary((char*)binary, size); setType(TYPE_EXECUTABLE); diff --git a/projects/clr/rocclr/runtime/device/pal/palprogram.hpp b/projects/clr/rocclr/runtime/device/pal/palprogram.hpp index 068c4a552f..fceded4764 100644 --- a/projects/clr/rocclr/runtime/device/pal/palprogram.hpp +++ b/projects/clr/rocclr/runtime/device/pal/palprogram.hpp @@ -54,11 +54,15 @@ class Segment : public amd::HeapObject { uint64_t gpuAddress(size_t offset) const { return gpuAccess_->vmAddress() + offset; } //! Returns address for CPU access in the segment - void* cpuAddress(size_t offset) const { return cpuAccess_->data() + offset; } + void* cpuAddress(size_t offset) const + { return ((cpuAccess_ != nullptr) ? cpuAccess_->data() : cpuMem_) + offset; } + + void DestroyCpuAccess(); private: - Memory* gpuAccess_; //!< GPU memory for segment access - Memory* cpuAccess_; //!< CPU memory for segment (backing store) + Memory* gpuAccess_; //!< GPU memory for segment access + Memory* cpuAccess_; //!< CPU memory for segment (backing store) + address cpuMem_; //!< CPU memory for segment without GPU direct access (backing store) }; class PALHSALoaderContext final : public Context { @@ -135,9 +139,9 @@ class HSAILProgram : public device::Program { void addGlobalStore(Memory* mem) { globalStores_.push_back(mem); } - void setCodeObjects(Memory* codeGpu, address codeCpu) { + void setCodeObjects(Segment* seg, Memory* codeGpu, address codeCpu) { codeSegGpu_ = codeGpu; - codeSegCpu_ = codeCpu; + codeSegment_ = seg; } const std::vector& globalStores() const { return globalStores_; } @@ -169,9 +173,6 @@ class HSAILProgram : public device::Program { //! Returns code segement on GPU const Memory& codeSegGpu() const { return *codeSegGpu_; } - //! Returns code segement on CPU - address codeSegCpu() const { return codeSegCpu_; } - //! Returns CPU address for a kernel uint64_t findHostKernelAddress(uint64_t devAddr) const { return loader_->FindHostAddress(devAddr); @@ -219,9 +220,11 @@ class HSAILProgram : public device::Program { virtual bool isElf(const char* bin) const { return amd::isElfMagic(bin); - // return false; } + //! Destroys CPU allocations in the code segment + void DestroySegmentCpuAccess() const { codeSegment_->DestroyCpuAccess(); } + private: //! Disable default copy constructor HSAILProgram(const HSAILProgram&); @@ -242,7 +245,7 @@ class HSAILProgram : public device::Program { std::vector globalStores_; //!< Global memory for the program Memory* kernels_; //!< Table with kernel object pointers Memory* codeSegGpu_; //!< GPU memory with code objects - address codeSegCpu_; //!< CPU memory with code objects + Segment* codeSegment_; //!< Pointer to the code segment for this program uint maxScratchRegs_; //!< Maximum number of scratch regs used in the program by individual kernel std::list staticSamplers_; //!< List od internal static samplers