summaryrefslogtreecommitdiff
path: root/libcuda
diff options
context:
space:
mode:
authorAndrew M. B. Boktor <[email protected]>2012-08-17 14:45:03 -0800
committerAndrew Boktor <[email protected]>2014-08-14 13:48:54 -0700
commit9b49af32a493752503cd414e5a15063ac0bc98a1 (patch)
tree366f3f8d300711222f39e84b659100052411ace7 /libcuda
parent7757c7e26172c5d6452ba2b1b051df3fd28505d3 (diff)
On demand loading of fatbins
Experimental library support (diff abstract_hardware_model.cc) (currently broken because of undocumented cudaGetExportTable function in the cuda rt api) [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 13793]
Diffstat (limited to 'libcuda')
-rw-r--r--libcuda/cuda_runtime_api.cc212
-rw-r--r--libcuda/cuobjdump.l5
-rw-r--r--libcuda/cuobjdump.y5
3 files changed, 124 insertions, 98 deletions
diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc
index 58ffd4d..a986f3e 100644
--- a/libcuda/cuda_runtime_api.cc
+++ b/libcuda/cuda_runtime_api.cc
@@ -108,6 +108,9 @@
#include <time.h>
#include <stdarg.h>
#include <iostream>
+#include <string>
+#include <sstream>
+#include <fstream>
#ifdef OPENGL_SUPPORT
#define GL_GLEXT_PROTOTYPES
#ifdef __APPLE__
@@ -1174,6 +1177,7 @@ private:
};
std::list<cuobjdumpSection*> cuobjdumpSectionList;
+std::list<cuobjdumpSection*> libSectionList;
// sectiontype: 0 for ptx, 1 for elf
void addCuobjdumpSection(int sectiontype){
@@ -1222,21 +1226,26 @@ void setCuobjdumpsassfilename(const char* filename){
extern "C" int cuobjdump_parse();
extern "C" FILE *cuobjdump_in;
-//! Call cuobjdump to extract everything (-elf -sass -ptx) to a file
+//! Call cuobjdump to extract everything (-elf -sass -ptx)
/*!
* This Function extract the whole PTX (for all the files) using cuobjdump
- * to _cuobjdump_complete_output_XXXXXX
+ * to _cuobjdump_complete_output_XXXXXX then runs a parser to chop it up with each binary in
+ * its own file
+ * It is also responsible for extracting the libraries linked to the binary if the option is
+ * enabled
* */
void extract_code_using_cuobjdump(){
+ CUctx_st *context = GPGPUSim_Context();
char command[1000];
char fname[1024];
snprintf(fname,1024,"_cuobjdump_complete_output_XXXXXX");
int fd=mkstemp(fname);
close(fd);
-
- //! Running cuobjdump using dynamic link to current process
- snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass /proc/%d/exe > %s",getpid(),fname);
+ std::stringstream pid;
+ pid << getpid();
+ // Running cuobjdump using dynamic link to current process
+ snprintf(command,1000,"$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass /proc/%s/exe > %s",pid.str().c_str(),fname);
printf("Running cuobjdump using \"%s\"\n", command);
int result = system(command);
if(result) {printf("ERROR: Failed to execute: %s\n", command); exit(1);}
@@ -1247,9 +1256,62 @@ void extract_code_using_cuobjdump(){
cuobjdump_parse();
fclose(cuobjdump_in);
printf("Done parsing!!!\n");
+
+ if (context->get_device()->get_gpgpu()->get_config().experimental_lib_support()){
+ //Experimental library support
+ //Currently only for cufft
+
+ std::stringstream cmd;
+ cmd << "ldd /proc/" << pid.str() << "/exe | grep $CUDA_INSTALL_PATH | awk \'{print $3}\' > _tempfile_.txt";
+ result = system(cmd.str().c_str());
+ if(result){
+ std::cout << "Failed to execute: " << cmd << std::endl;
+ exit(1);
+ }
+ std::ifstream libsf;
+ libsf.open("_tempfile_.txt");
+ if(!libsf.is_open()) {
+ std::cout << "Failed to open: _tempfile_.txt" << std::endl;
+ exit(1);
+ }
+
+ //Save the original section list
+ std::list<cuobjdumpSection*> tmpsl = cuobjdumpSectionList;
+ cuobjdumpSectionList.clear();
+
+ std::string line;
+ std::getline(libsf, line);
+ std::cout << "DOING: " << line << std::endl;
+ int cnt=1;
+ while(libsf.good()){
+ std::stringstream libcodfn;
+ libcodfn << "_cuobjdump_complete_lib_" << cnt << "_";
+ cmd.str(""); //resetting
+ cmd << "$CUDA_INSTALL_PATH/bin/cuobjdump -ptx -elf -sass ";
+ cmd << line;
+ cmd << " > ";
+ cmd << libcodfn.str();
+ std::cout << "Running cuobjdump on " << line << std::endl;
+ std::cout << "Using command: " << cmd.str() << std::endl;
+ result = system(cmd.str().c_str());
+ if(result) {printf("ERROR: Failed to execute: %s\n", command); exit(1);}
+ std::cout << "Done" << std::endl;
+
+ std::cout << "Trying to parse " << libcodfn << std::endl;
+ cuobjdump_in = fopen(libcodfn.str().c_str(), "r");
+ cuobjdump_parse();
+ fclose(cuobjdump_in);
+ std::getline(libsf, line);
+ }
+ libSectionList = cuobjdumpSectionList;
+
+ //Restore the original section list
+ cuobjdumpSectionList = tmpsl;
+ }
}
//! Read file into char*
+//TODO: convert this to C++ streams, will be way cleaner
char* readfile (const std::string filename){
assert (filename != "");
FILE* fp = fopen(filename.c_str(),"r");
@@ -1257,13 +1319,13 @@ char* readfile (const std::string filename){
std::cout << "ERROR: Could not open file %s for reading\n" << filename << std::endl;
assert (0);
}
- //! finding size of the file
+ // finding size of the file
int filesize= 0;
fseek (fp , 0 , SEEK_END);
filesize = ftell (fp);
fseek (fp, 0, SEEK_SET);
- //! allocate and copy the entire ptx
+ // allocate and copy the entire ptx
char* ret = (char*)malloc((filesize +1)* sizeof(char));
fread(ret,1,filesize,fp);
ret[filesize]='\0';
@@ -1271,7 +1333,7 @@ char* readfile (const std::string filename){
return ret;
}
-//Function that helps debugging
+//! Function that helps debugging
void printSectionList(std::list<cuobjdumpSection*> sl) {
std::list<cuobjdumpSection*>::iterator iter;
for ( iter = sl.begin();
@@ -1282,7 +1344,7 @@ void printSectionList(std::list<cuobjdumpSection*> sl) {
}
}
-//remove unecessary sm versions from the section list
+//! Remove unecessary sm versions from the section list
std::list<cuobjdumpSection*> pruneSectionList(std::list<cuobjdumpSection*> cuobjdumpSectionList, CUctx_st *context) {
unsigned forced_max_capability = context->get_device()->get_gpgpu()->get_config().get_forced_max_capability();
@@ -1328,10 +1390,8 @@ std::list<cuobjdumpSection*> pruneSectionList(std::list<cuobjdumpSection*> cuobj
}
-/*!
- * Within the section list, find the ELF section corresponding to a given identifier
- */
-cuobjdumpELFSection* findelfsection(std::list<cuobjdumpSection*> sectionlist, const std::string identifier){
+//! Within the section list, find the ELF section corresponding to a given identifier
+cuobjdumpELFSection* findELFSectionInList(std::list<cuobjdumpSection*> sectionlist, const std::string identifier){
std::list<cuobjdumpSection*>::iterator iter;
for ( iter = sectionlist.begin();
@@ -1344,14 +1404,22 @@ cuobjdumpELFSection* findelfsection(std::list<cuobjdumpSection*> sectionlist, co
return elfsection;
}
}
+ return NULL;
+}
+
+//! Find an ELF section in all the known lists
+cuobjdumpELFSection* findELFSection(const std::string identifier){
+ cuobjdumpELFSection* sec = findELFSectionInList(cuobjdumpSectionList, identifier);
+ if (sec!=NULL)return sec;
+ sec = findELFSectionInList(libSectionList, identifier);
+ if (sec!=NULL)return sec;
+ std::cout << "Cound not find " << identifier << std::endl;
assert(0 && "Could not find the required ELF section");
return NULL;
}
-/*!
- * Within the section list, find the PTX section corresponding to a given identifier
- */
-cuobjdumpPTXSection* findptxsection(std::list<cuobjdumpSection*> sectionlist, const std::string identifier){
+//! Within the section list, find the PTX section corresponding to a given identifier
+cuobjdumpPTXSection* findPTXSectionInList(std::list<cuobjdumpSection*> sectionlist, const std::string identifier){
std::list<cuobjdumpSection*>::iterator iter;
for ( iter = sectionlist.begin();
iter != sectionlist.end();
@@ -1363,28 +1431,46 @@ cuobjdumpPTXSection* findptxsection(std::list<cuobjdumpSection*> sectionlist, co
return ptxsection;
}
}
- std::cout << identifier << std::endl;
+ return NULL;
+}
+
+//! Find an PTX section in all the known lists
+cuobjdumpPTXSection* findPTXSection(const std::string identifier){
+ cuobjdumpPTXSection* sec = findPTXSectionInList(cuobjdumpSectionList, identifier);
+ if (sec!=NULL)return sec;
+ sec = findPTXSectionInList(libSectionList, identifier);
+ if (sec!=NULL)return sec;
+ std::cout << "Cound not find " << identifier << std::endl;
assert(0 && "Could not find the required PTX section");
return NULL;
}
+
+//! Extract the code using cuobjdump and remove unnecessary sections
void cuobjdumpInit(){
CUctx_st *context = GPGPUSim_Context();
-
extract_code_using_cuobjdump(); //extract all the output of cuobjdump to _cuobjdump_*.*
-
cuobjdumpSectionList = pruneSectionList(cuobjdumpSectionList, context);
}
+std::map<int, std::string> fatbinmap;
+std::map<int, bool>fatbin_registered;
-
+//! Keep track of the association between filename and cubin handle
void cuobjdumpRegisterFatBinary(unsigned int handle, char* filename){
+ fatbinmap[handle] = filename;
+}
+
+//! Either submit PTX for simulation or convert SASS to PTXPlus and submit it
+void cuobjdumpParseBinary(unsigned int handle){
+ if(fatbin_registered[handle]) return;
+ fatbin_registered[handle] = true;
CUctx_st *context = GPGPUSim_Context();
- std::string fname = filename;
- cuobjdumpPTXSection* ptx = findptxsection(cuobjdumpSectionList, fname);
+ std::string fname = fatbinmap[handle];
+ cuobjdumpPTXSection* ptx = findPTXSection(fname);
symbol_table *symtab;
char *ptxcode;
@@ -1396,7 +1482,7 @@ void cuobjdumpRegisterFatBinary(unsigned int handle, char* filename){
ptxcode = readfile(override_ptx_name);
}
if(context->get_device()->get_gpgpu()->get_config().convert_to_ptxplus() ) {
- cuobjdumpELFSection* elfsection = findelfsection(cuobjdumpSectionList, ptx->getIdentifier());
+ cuobjdumpELFSection* elfsection = findELFSection(ptx->getIdentifier());
assert (elfsection!= NULL);
char *ptxplus_str = gpgpu_ptx_sim_convert_ptx_and_sass_to_ptxplus(
ptx->getPTXfilename(),
@@ -1419,76 +1505,6 @@ void cuobjdumpRegisterFatBinary(unsigned int handle, char* filename){
//TODO: Remove temporarily files as per configurations
}
-
-// Currently not used
-void useCuobjdump() {
-
- CUctx_st *context = GPGPUSim_Context();
-
- unsigned source_num=1;
- extract_code_using_cuobjdump(); //extract all the output of cuobjdump to _cuobjdump_*.*
-
- // There is variation in the order by which the cubins are registered. It was observed that
- // the order is correct when the first section is a PTX section and is reversed when the
- // first section is an ELF section
- bool reverse=false;
- if (dynamic_cast<cuobjdumpELFSection*>(cuobjdumpSectionList.front()) != NULL)reverse=true;
-
- cuobjdumpSectionList = pruneSectionList(cuobjdumpSectionList, context);
- unsigned total_ptx_files = cuobjdumpSectionList.size()/2 + 1;
-
- for ( std::list<cuobjdumpSection*>::iterator iter2 = cuobjdumpSectionList.begin();
- iter2 != cuobjdumpSectionList.end();
- iter2++
- ){
- if (dynamic_cast<cuobjdumpPTXSection*>(*iter2) != NULL)
- {
- int cubin_handle;
- if(reverse) cubin_handle = total_ptx_files-source_num;
- else cubin_handle = source_num;
- cuobjdumpPTXSection *iter = dynamic_cast<cuobjdumpPTXSection*>(*iter2);
- symbol_table *symtab;
- char *ptxcode = readfile(iter->getPTXfilename());
- if(context->get_device()->get_gpgpu()->get_config().convert_to_ptxplus() ) {
- cuobjdumpELFSection* elfsection = findelfsection(cuobjdumpSectionList, iter->getIdentifier());
- assert (elfsection!= NULL);
- char *ptxplus_str = gpgpu_ptx_sim_convert_ptx_and_sass_to_ptxplus(
- iter->getPTXfilename(),
- elfsection->getELFfilename(),
- elfsection->getSASSfilename());
- symtab=gpgpu_ptx_sim_load_ptx_from_string(ptxplus_str,cubin_handle);
- printf("Adding %s with cubin handle %u\n", iter->getPTXfilename().c_str(), cubin_handle);
- context->add_binary(symtab, cubin_handle);
- gpgpu_ptxinfo_load_from_string( ptxcode, cubin_handle);
- delete[] ptxplus_str;
- } else {
- symtab=gpgpu_ptx_sim_load_ptx_from_string(ptxcode, cubin_handle);
- printf("Adding %s with cubin handle %u\n", iter->getPTXfilename().c_str(), cubin_handle);
- context->add_binary(symtab, cubin_handle);
- gpgpu_ptxinfo_load_from_string( ptxcode, cubin_handle);
- }
- source_num++;
-
- load_static_globals(symtab,STATIC_ALLOC_LIMIT,0xFFFFFFFF,context->get_device()->get_gpgpu());
- load_constants(symtab,STATIC_ALLOC_LIMIT,context->get_device()->get_gpgpu());
- }
- }
- if(!keep_intermediate_files()){
- char rm_commandline[1024];
-
- snprintf(rm_commandline,1024,"rm -f _cuobjdump_*");
-
- printf("GPGPU-Sim PTX: removing temporary files using \"%s\"\n", rm_commandline);
- int rm_result = system(rm_commandline);
- if( rm_result != 0 ) {
- printf("GPGPU-Sim PTX: ERROR ** while removing temporary files %d\n", rm_result);
- exit(1);
- }
- }
-
-}
-
-
void** CUDARTAPI __cudaRegisterFatBinary( void *fatCubin )
{
#if (CUDART_VERSION < 2010)
@@ -1596,6 +1612,12 @@ void __cudaUnregisterFatBinary(void **fatCubinHandle)
;
}
+cudaError_t cudaGetExportTable(
+ const void **ppExportTable,
+ const cudaUUID_t *pExportTableId) {
+ return g_last_cudaError = cudaSuccess;
+}
+
cudaError_t cudaDeviceReset ( void ) {
// Should reset the simulated GPU
return g_last_cudaError = cudaSuccess;
@@ -1622,6 +1644,7 @@ void CUDARTAPI __cudaRegisterFunction(
unsigned fat_cubin_handle = (unsigned)(unsigned long long)fatCubinHandle;
printf("GPGPU-Sim PTX: __cudaRegisterFunction %s : hostFun 0x%p, fat_cubin_handle = %u\n",
deviceFun, hostFun, fat_cubin_handle);
+ cuobjdumpParseBinary(fat_cubin_handle);
context->register_function( fat_cubin_handle, hostFun, deviceFun );
}
@@ -1637,6 +1660,7 @@ extern void __cudaRegisterVar(
{
printf("GPGPU-Sim PTX: __cudaRegisterVar: hostVar = %p; deviceAddress = %s; deviceName = %s\n", hostVar, deviceAddress, deviceName);
printf("GPGPU-Sim PTX: __cudaRegisterVar: Registering const memory space of %d bytes\n", size);
+ cuobjdumpParseBinary((unsigned)(unsigned long long)fatCubinHandle);
fflush(stdout);
if ( constant && !global && !ext ) {
gpgpu_ptx_sim_register_const_variable(hostVar,deviceName,size);
diff --git a/libcuda/cuobjdump.l b/libcuda/cuobjdump.l
index e782c17..d264338 100644
--- a/libcuda/cuobjdump.l
+++ b/libcuda/cuobjdump.l
@@ -107,13 +107,14 @@ newlines {newline}+
<header>"has debug info"{newline}
/* Looking for the identifier (filename) then the header is done */
-<endheader>[[:alnum:]_\.]+ yylval.string_value = strdup(yytext); yy_pop_state(); return FILENAME;
+ /* <endheader>[[:alnum:]_\./]+ yylval.string_value = strdup(yytext); yy_pop_state(); return FILENAME; */
+<endheader>{notnewline}+ yylval.string_value = strdup(yytext); yy_pop_state(); return FILENAME;
{newline} return NEWLINE;
/*Reached end of file*/
-<<EOF>> return 0;
+<<EOF>> BEGIN(INITIAL);return 0;
/*No other rule matched. Throw an error*/
. cuobjdump_error("Invalid token");
diff --git a/libcuda/cuobjdump.y b/libcuda/cuobjdump.y
index b8e9c11..ec97283 100644
--- a/libcuda/cuobjdump.y
+++ b/libcuda/cuobjdump.y
@@ -61,7 +61,8 @@ char filename [1024];
%%
-program : emptylines section
+program : {printf("######### cuobjdump parser ########\n");}
+ emptylines section
| program section;
emptylines : emptylines NEWLINE
@@ -103,7 +104,7 @@ ptxcode : ptxcode PTXLINE {fprintf(ptxfile, "%s", $2);}
elfcode : elfcode ELFLINE {fprintf(elffile, "%s", $2);}
| ;
-sasscode : sasscode SASSLINE {fprintf(sassfile, "%s", $2)}
+sasscode : sasscode SASSLINE {fprintf(sassfile, "%s", $2);}
| ;