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
Αυτή η υποβολή περιλαμβάνεται σε:
foreman
2014-10-03 04:30:34 -04:00
γονέας 1001028b9b
υποβολή f7c2190e63
5 αρχεία άλλαξαν με 101 προσθήκες και 62 διαγραφές
@@ -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<bifbase*>(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<char*>(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<const aclMetadata*>(roSec);
bool success = false;
switch (query) {
default: break;
case RT_CPU_BARRIER_NAMES:
@@ -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
@@ -5,6 +5,7 @@
#define _CL_LIB_UTILS_0_8_H_
#include "v0_8/aclTypes.h"
#include <string>
#include <sstream>
#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<std::string> splitSpaceSeparatedString(char *str)
{
std::string s(str);
std::stringstream ss(s);
std::istream_iterator<std::string> beg(ss), end;
std::vector<std::string> vec(beg, end);
return vec;
}
#endif // _CL_LIB_UTILS_0_8_H_
@@ -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=");
@@ -15,6 +15,7 @@
#include <sstream>
#include <cstdio>
#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<std::string> vKernels = splitSpaceSeparatedString(kernelNames);
delete kernelNames;
std::vector<std::string>::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<uint>(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<uint>(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<char*>(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<char*>(mem), size);
buildLog_ += aclGetCompilerLog(dev().hsaCompiler());
return true;
}
bool