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
Αυτή η υποβολή περιλαμβάνεται σε:
@@ -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
|
||||
|
||||
Αναφορά σε νέο ζήτημα
Block a user