From f7c2190e634762f423beec7115089021d276d4ee Mon Sep 17 00:00:00 2001
From: foreman
Date: Fri, 3 Oct 2014 04:30:34 -0400
Subject: [PATCH] P4 to Git Change 1083876 by emankov@em-hsa-amd on 2014/10/03
04:25:16
ECR #333753 - HSA RT/Compiler Lib/Performance: Elimination of HSAIL text usage in RT
Extracting HSAIL from the binary and parsing it for the kernel names in RT were replaced with aclQueryInfo call for RT_KERNEL_NAMES.
Kernel names are obtained now from the corresponding metadata symbols names, which are already presented in BIF at kernel finalization stage.
Side effect: performance improvement
Next Step: Performance: elimination of BRIG disassembling to HSAIL as obligatory stage in Compiler Lib (previously was needed only by RT).
Testing: pre check-in, ocl conformnace 2.0 (basic, api, compiler, workgroups, device_execution)
Reviewers: Stanislav Mekhanoshin, German Andryeyev, Brian Sumner
Affected files ...
... //depot/stg/opencl/drivers/opencl/compiler/lib/api/v0_8/acl.cpp#20 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/v0_8/if_acl.cpp#51 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/include/v0_8/aclEnums.h#13 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/loaders/bif/bifbase.cpp#50 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/loaders/bif/bifbase.hpp#22 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/utils/v0_8/libUtils.h#11 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpukernel.cpp#266 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.cpp#179 edit
... //depot/stg/opencl/drivers/opencl/tests/ocltst/module/complib/CLEnumCheck.cpp#37 edit
---
.../lib/backends/common/v0_8/if_acl.cpp | 60 +++++++++++--
rocclr/compiler/lib/include/v0_8/aclEnums.h | 3 +-
rocclr/compiler/lib/utils/v0_8/libUtils.h | 10 +++
rocclr/runtime/device/gpu/gpukernel.cpp | 5 +-
rocclr/runtime/device/gpu/gpuprogram.cpp | 85 +++++++------------
5 files changed, 101 insertions(+), 62 deletions(-)
diff --git a/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp b/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
index b2126894cb..a79a17d149 100644
--- a/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
+++ b/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
@@ -2256,22 +2256,72 @@ if_aclQueryInfo(aclCompiler *cl,
void *ptr,
size_t *size)
{
- if (!size)
+ if (!size) {
return ACL_ERROR;
+ }
const oclBIFSymbolStruct* sym = findBIF30SymStruct(symOpenclMeta);
assert(sym && "symbol not found");
- std::string symbol = sym->str[PRE] + std::string(kernel) + sym->str[POST];
+ aclSections secID = sym->sections[0];
+ std::string pre = std::string(sym->str[PRE]);
+ std::string post = std::string(sym->str[POST]);
+ if (RT_KERNEL_NAMES == query) {
+ bifbase *elfBin = reinterpret_cast(binary->bin);
+ if (!elfBin) {
+ return ACL_ELF_ERROR;
+ }
+ bifbase::SymbolVector symbols, kernels;
+ elfBin->getSectionSymbols(secID, symbols);
+ size_t totSize = 0;
+ if (!symbols.empty()) {
+ std::size_t beg = 0, begKernel = 0, end = 0, endKernel = 0, endSize = 0;
+ const oclBIFSymbolStruct* symKernel = findBIF30SymStruct(symOpenclKernel);
+ assert(symKernel && "symbol not found");
+ std::string preKernel = std::string(symKernel->str[PRE]);
+ std::string postKernel = std::string(symKernel->str[POST]);
+ for (bifbase::SymbolVector::iterator it = symbols.begin(); it != symbols.end(); ++it) {
+ beg = (*it).find(pre);
+ if (std::string::npos == beg) continue;
+ beg += pre.size();
+ begKernel = (*it).find(preKernel, beg);
+ if (std::string::npos != begKernel) {
+ beg = begKernel + preKernel.size();
+ end = (*it).rfind(postKernel);
+ endSize = postKernel.size();
+ } else {
+ end = (*it).rfind(post);
+ }
+ if (std::string::npos == end) continue;
+ endSize += post.size();
+ if (end <= beg || end != (*it).size() - endSize) continue;
+ std::string kernel((*it).substr(beg, (*it).size() - beg - endSize) + " ");
+ totSize += kernel.size();
+ kernels.push_back(kernel);
+ }
+ }
+ if (!ptr) {
+ *size = totSize > 0 ? totSize + 1 : 0;
+ return ACL_SUCCESS;
+ } else if (*size >= totSize && totSize > 0) {
+ char* tmp = reinterpret_cast(ptr);
+ for (bifbase::SymbolVector::iterator it = kernels.begin(); it != kernels.end(); ++it) {
+ memcpy(tmp, (*it).c_str(), (*it).size());
+ tmp += (*it).size();
+ }
+ *(tmp++) = '\0';
+ return ACL_SUCCESS;
+ }
+ return ACL_ERROR;
+ }
size_t roSize;
acl_error error_code;
- const void* roSec = cl->clAPI.extSym(cl, binary, &roSize,
- sym->sections[0], symbol.c_str(), &error_code);
+ std::string symbol = pre + std::string(kernel) + post;
+ const void* roSec = cl->clAPI.extSym(cl, binary, &roSize, secID, symbol.c_str(), &error_code);
if (error_code != ACL_SUCCESS) return error_code;
if (roSec == NULL || roSize == 0) {
return ACL_ELF_ERROR;
}
const aclMetadata *md = reinterpret_cast(roSec);
bool success = false;
-
switch (query) {
default: break;
case RT_CPU_BARRIER_NAMES:
diff --git a/rocclr/compiler/lib/include/v0_8/aclEnums.h b/rocclr/compiler/lib/include/v0_8/aclEnums.h
index 91058b871b..451ff72126 100644
--- a/rocclr/compiler/lib/include/v0_8/aclEnums.h
+++ b/rocclr/compiler/lib/include/v0_8/aclEnums.h
@@ -201,7 +201,8 @@ typedef enum _rt_query_types_enum_0_8 {
RT_DEVICE_ENQUEUE = 11,
RT_KERNEL_INDEX = 12,
RT_KERNEL_NAME = 13,
- RT_LAST_TYPE = 14
+ RT_KERNEL_NAMES = 14,
+ RT_LAST_TYPE = 15
} aclQueryType_0_8;
//! An enumeration for the various GPU capabilities
diff --git a/rocclr/compiler/lib/utils/v0_8/libUtils.h b/rocclr/compiler/lib/utils/v0_8/libUtils.h
index 1f85bb044f..60a6d9340d 100644
--- a/rocclr/compiler/lib/utils/v0_8/libUtils.h
+++ b/rocclr/compiler/lib/utils/v0_8/libUtils.h
@@ -5,6 +5,7 @@
#define _CL_LIB_UTILS_0_8_H_
#include "v0_8/aclTypes.h"
#include
+#include
#include "library.hpp"
// Utility function to set a flag in option structure
// of the aclDevCaps.
@@ -176,4 +177,13 @@ enum scId {
SC_LAST,
};
+inline std::vector splitSpaceSeparatedString(char *str)
+{
+ std::string s(str);
+ std::stringstream ss(s);
+ std::istream_iterator beg(ss), end;
+ std::vector vec(beg, end);
+ return vec;
+}
+
#endif // _CL_LIB_UTILS_0_8_H_
diff --git a/rocclr/runtime/device/gpu/gpukernel.cpp b/rocclr/runtime/device/gpu/gpukernel.cpp
index 61614d9045..4417275d52 100644
--- a/rocclr/runtime/device/gpu/gpukernel.cpp
+++ b/rocclr/runtime/device/gpu/gpukernel.cpp
@@ -9,6 +9,7 @@
#include "device/gpu/gpusched.hpp"
#include "platform/commandqueue.hpp"
#include "utils/options.hpp"
+#include "utils/bif_section_labels.hpp"
#include "acl.h"
#include "SCShadersR678XXCommon.h"
@@ -3513,8 +3514,10 @@ bool
HSAILKernel::init(bool finalize)
{
acl_error error;
+ const oclBIFSymbolStruct* sym = findBIF30SymStruct(symOpenclKernel);
+ assert(sym && "symbol not found");
+ std::string openClKernelName(std::string("&") + sym->str[PRE] + name() + sym->str[POST]);
//compile kernel down to ISA
- std::string openClKernelName("&__OpenCL_" + name() + "_kernel");
if (finalize) {
std::string options(compileOptions_.c_str());
options.append(" -just-kernel=");
diff --git a/rocclr/runtime/device/gpu/gpuprogram.cpp b/rocclr/runtime/device/gpu/gpuprogram.cpp
index a938e04008..777e1a6ade 100644
--- a/rocclr/runtime/device/gpu/gpuprogram.cpp
+++ b/rocclr/runtime/device/gpu/gpuprogram.cpp
@@ -15,6 +15,7 @@
#include
#include
#include "utils/options.hpp"
+#include "utils/libUtils.h"
#include "newcore.h"
extern "C" bool
@@ -2159,76 +2160,50 @@ HSAILProgram::linkImpl(amd::option::Options* options)
buildLog_ += "Error while BRIG Codegen phase: loading BRIG globals in the ELF \n";
return false;
}
- // We need to pull out kernels' names for finalizing kernels
- //! @todo Rewrite the below code, if another way to obtain kernel names
- //! appears in the compiler library
- size_t hsailSize = 0;
- const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symHSAILText);
- assert(symbol && "symbol not found");
- std::string symName = symbol->str[PRE] + std::string("main") + symbol->str[POST];
- const void *hsailText = aclExtractSymbol(dev().hsaCompiler(), binaryElf_,
- &hsailSize, aclCODEGEN, symName.c_str(), &errorCode);
+ size_t kernelNamesSize = 0;
+ errorCode = aclQueryInfo(dev().hsaCompiler(), binaryElf_, RT_KERNEL_NAMES, NULL, NULL, &kernelNamesSize);
if (errorCode != ACL_SUCCESS) {
- buildLog_ += "Error while reading out the HSAIL from the ELF \n" ;
+ buildLog_ += "Error while Finalization phase: kernel names query from the ELF failed\n";
return false;
}
- std::string hsailProgram((char *)hsailText, hsailSize);
- HSAILProgram_ = hsailProgram;
- if (!HSAILProgram_.empty()) {
- bool dynamicParallelism = false;
- // Find out the name of the kernel. Works for multiple kernels
- int pos = 0;
- while (true) {
- std::string findString = "kernel &";
- size_t kernelNPos = HSAILProgram_.find(findString, pos);
- if (kernelNPos == std::string::npos) {
- break;
- }
- size_t kernelEndNPos = HSAILProgram_.find("l(", kernelNPos);
- pos = kernelEndNPos + 1;
- if (kernelEndNPos == std::string::npos) {
- break;
- }
- // "kernel &" is 8
- // "__OpenCL_" is 9
- // "_kerne" is 6
- // We can drop all this with a compiler tweak later
- std::string kernelName = HSAILProgram_.substr(kernelNPos + 8 + 9,
- kernelEndNPos -
- (kernelNPos + 8 + 9) - 6);
- HSAILKernel *aKernel = new HSAILKernel(kernelName, this,
- options->origOptionStr + hsailOptions());
+ if (kernelNamesSize > 0) {
+ char* kernelNames = new char[kernelNamesSize];
+ errorCode = aclQueryInfo(dev().hsaCompiler(), binaryElf_, RT_KERNEL_NAMES, NULL, kernelNames, &kernelNamesSize);
+ if (errorCode != ACL_SUCCESS) {
+ buildLog_ += "Error while Finalization phase: kernel's Metadata is corrupted in the ELF\n";
+ delete kernelNames;
+ return false;
+ }
+ std::vector vKernels = splitSpaceSeparatedString(kernelNames);
+ delete kernelNames;
+ std::vector::iterator it = vKernels.begin();
+ bool dynamicParallelism = false;
+ for (it; it != vKernels.end(); ++it) {
+ std::string kernelName = *it;
+ HSAILKernel *aKernel = new HSAILKernel(kernelName, this, options->origOptionStr + hsailOptions());
if (!aKernel->init(finalize)) {
return false;
}
buildLog_ += aKernel->buildLog();
- aKernel->setUniformWorkGroupSize(options
- ->oVariables->UniformWorkGroupSize);
+ aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize);
kernels()[kernelName] = aKernel;
dynamicParallelism |= aKernel->dynamicParallelism();
- // Find max scratch regs used in the program
- // It's used for scratch buffer preallocation with
- // dynamic parallelism, since runtime doesn't know
- // which child kernel will be called
- maxScratchRegs_ = std::max(
- static_cast(aKernel->workGroupInfo()->scratchRegs_),
- maxScratchRegs_);
+ // Find max scratch regs used in the program. It's used for scratch buffer preallocation
+ // with dynamic parallelism, since runtime doesn't know which child kernel will be called
+ maxScratchRegs_ = std::max(static_cast(aKernel->workGroupInfo()->scratchRegs_), maxScratchRegs_);
}
-
// Allocate kernel table for device enqueuing
if (dynamicParallelism && !allocKernelTable()) {
return false;
}
-
- // Save the binary in the interface class
- size_t size = 0;
- void *mem = NULL;
- aclWriteToMem(binaryElf_, &mem, &size);
- setBinary(static_cast(mem), size);
- buildLog_ += aclGetCompilerLog(dev().hsaCompiler());
- return true;
}
- return false;
+ // Save the binary in the interface class
+ size_t size = 0;
+ void *mem = NULL;
+ aclWriteToMem(binaryElf_, &mem, &size);
+ setBinary(static_cast(mem), size);
+ buildLog_ += aclGetCompilerLog(dev().hsaCompiler());
+ return true;
}
bool