diff --git a/amexec/inc/model_process.h b/amexec/inc/model_process.h index de2bc48..c0fa939 100755 --- a/amexec/inc/model_process.h +++ b/amexec/inc/model_process.h @@ -46,6 +46,11 @@ public: * @return result */ Result CreateDesc(); + + /** + * @brief PrintDesc + */ + Result PrintDesc(); /** * @brief destroy desc @@ -59,7 +64,13 @@ public: * @return result */ Result CreateInput(void *inputDataBuffer, size_t bufferSize); - + + /** + * @brief create model input + * @return result + */ + Result CreateZeroInput(); + /** * @brief destroy input resource */ @@ -103,4 +114,6 @@ private: aclmdlDesc *modelDesc_; aclmdlDataset *input_; aclmdlDataset *output_; + size_t numInputs_; + size_t numOutputs_; }; \ No newline at end of file diff --git a/amexec/inc/sample_process.h b/amexec/inc/sample_process.h index 425b45f..95b1d21 100755 --- a/amexec/inc/sample_process.h +++ b/amexec/inc/sample_process.h @@ -12,6 +12,7 @@ #pragma once #include "utils.h" #include "acl/acl.h" +#include using namespace std; /** diff --git a/amexec/inc/utils.h b/amexec/inc/utils.h index 6fc942c..d14cef9 100755 --- a/amexec/inc/utils.h +++ b/amexec/inc/utils.h @@ -21,8 +21,13 @@ #include #include #include +#include +#include +#include +#include #define INFO_LOG(fmt, args...) fprintf(stdout, "[INFO] " fmt "\n", ##args) +#define DEBUG_LOG(fmt, args...) fprintf(stdout, "[DEBUG] " fmt "\n", ##args) #define WARN_LOG(fmt, args...) fprintf(stdout, "[WARN] " fmt "\n", ##args) #define ERROR_LOG(fmt, args...) fprintf(stdout, "[ERROR] " fmt "\n", ##args) @@ -72,6 +77,10 @@ public: static double InferenceTimeAverage(double *x, int len); static double InferenceTimeAverageWithoutFirst(double *x, int len); + + static void ProfilerJson(bool isprof, map& params); + + static void DumpJson(bool isdump, map& params); }; #pragma once diff --git a/amexec/out/amexec b/amexec/out/amexec index aa42e9e..273dd37 100755 Binary files a/amexec/out/amexec and b/amexec/out/amexec differ diff --git a/amexec/src/main.cpp b/amexec/src/main.cpp index 7c81c56..8cef44a 100755 --- a/amexec/src/main.cpp +++ b/amexec/src/main.cpp @@ -17,6 +17,10 @@ using namespace std; bool f_isTXT = false; bool g_isDevice = false; int loop = 1; +int32_t device = 0; +bool is_profi = false; +bool is_dump = false; +bool is_debug = false; string input_Ftype = ".bin"; string model_Ftype = ".om"; string check = ""; @@ -24,17 +28,19 @@ string check = ""; void InitAndCheckParams(int argc, char* argv[], map& params, vector& inputs) //void InitAndCheckParams(int argc, char* argv[], vector& params, vector& inputs) { - const char *optstring="m::i::o::f::hd::p::l::y::"; + const char *optstring="m::i::o::f::hd::p::l::y::e::g::"; int c,deb,index; struct option opts[]={{"model",required_argument,NULL,'m'}, {"input",required_argument,NULL,'i'}, {"output",required_argument,NULL,'o'}, {"outfmt",required_argument,NULL,'f'}, {"help",no_argument,NULL,1}, - {"dumpConf",required_argument,NULL,'d'}, - {"profConf",required_argument,NULL,'p'}, + {"dump",required_argument,NULL,'d'}, + {"profiler",required_argument,NULL,'p'}, {"loop",required_argument,NULL,'l'}, - {"dymBatch",required_argument,NULL,'y'}, + {"dymBatch",required_argument,NULL,'y'}, + {"device",required_argument,NULL,'e'}, + {"debug",required_argument,NULL,'g'}, {0,0,0,0}}; while((c=getopt_long(argc,argv,optstring,opts,&index))!=-1) { @@ -84,7 +90,7 @@ void InitAndCheckParams(int argc, char* argv[], map& params, vector break; case 'l': loop = Utils::str2num(optarg); - cout << "loop:" << loop << endl; + cout << "loop:" << loop << endl; if (loop > 100 || loop < 1) { printf("loop must in 1 to 100\n"); @@ -95,6 +101,18 @@ void InitAndCheckParams(int argc, char* argv[], map& params, vector // params.push_back(optarg); params['y'] = optarg; break; + case 'e': + device = Utils::str2num(optarg); + cout << "device:" << device << endl; + if (device > 255 || device < 0) + { + printf("device id must in 0 to 255\n"); + exit(0); + } + break; + case 'g': + params['g'] = optarg; + break; case 1: Utils::printHelpLetter(); exit(0); @@ -117,12 +135,29 @@ int main(int argc, char* argv[]) printf("Test Start!\n"); - if (params.empty() || inputs.empty()) { + if (params.empty()) { printf("Invalid params.\n"); printf("Execute sample failed.\n"); Utils::printHelpLetter(); return FAILED; } + + if (params['d'].compare("true") == 0) { + is_dump = true; + } + if (params['p'].compare("true") == 0) { + is_profi = true; + } + if (params['g'].compare("true") == 0) { + is_debug = true; + } + if (is_profi && is_dump){ + ERROR_LOG("dump and profiler can not both be true"); + return FAILED; + } + + Utils::ProfilerJson(is_profi, params); + Utils::DumpJson(is_dump, params); SampleProcess processSample; diff --git a/amexec/src/model_process.cpp b/amexec/src/model_process.cpp index d48e355..9dd3e34 100755 --- a/amexec/src/model_process.cpp +++ b/amexec/src/model_process.cpp @@ -21,7 +21,8 @@ extern bool g_isDevice; extern bool f_isTXT; ModelProcess::ModelProcess() :modelId_(0), modelMemSize_(0), modelWeightSize_(0), modelMemPtr_(nullptr), -modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr) +modelWeightPtr_(nullptr), loadFlag_(false), modelDesc_(nullptr), input_(nullptr), output_(nullptr), numInputs_(0), +numOutputs_(0) { } @@ -88,7 +89,84 @@ Result ModelProcess::CreateDesc() return SUCCESS; } - + +Result ModelProcess::PrintDesc() +{ aclError ret; + DEBUG_LOG("start print model description"); + size_t numInputs = aclmdlGetNumInputs(modelDesc_); + size_t numOutputs = aclmdlGetNumOutputs(modelDesc_); + DEBUG_LOG("NumInputs: %zu", numInputs); + DEBUG_LOG("NumOutputs: %zu", numOutputs); + + aclmdlIODims dimsInput; + aclmdlIODims dimsOutput; + aclmdlIODims dimsCurrentOutput; + for (size_t i = 0; i < numInputs; i++){ + DEBUG_LOG("the size of %zu input: %zu", i, aclmdlGetInputSizeByIndex(modelDesc_, i)); + ret = aclmdlGetInputDims(modelDesc_, i, &dimsInput); + DEBUG_LOG("the dims of %zu input:", i); + for (size_t j = 0; j < dimsInput.dimCount; j++){ + cout << dimsInput.dims[j] << " "; + } + cout << endl; + DEBUG_LOG("the name of %zu input: %s", i, aclmdlGetInputNameByIndex(modelDesc_, i)); + DEBUG_LOG("the Format of %zu input: %u", i, aclmdlGetInputFormat(modelDesc_, i)); + DEBUG_LOG("the DataType of %zu input: %u", i, aclmdlGetInputFormat(modelDesc_, i)); + } + for (size_t i = 0; i < numOutputs; i++){ + DEBUG_LOG("the size of %zu output: %zu", i, aclmdlGetOutputSizeByIndex(modelDesc_, i)); + ret = aclmdlGetOutputDims(modelDesc_, i, &dimsOutput); + DEBUG_LOG("the dims of %zu output:", i); + for (size_t j = 0; j < dimsOutput.dimCount; j++){ + cout <dimCount; j++) - { - if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) - {outstr << "\n" ;} - } - } + { + float out = *((float*)outData+i); + outstr << out << " "; + for (int j = 0; j < dim->dimCount; j++) + { + if (i !=0 && i%dim->dims[j] == 0 && dim->dims[j] > 10) + {outstr << "\n" ;} + } + } break; case 1: for (int i = 0; i < len/sizeof(aclFloat16); i++) @@ -579,5 +718,5 @@ void ModelProcess::Unload() } loadFlag_ = false; - INFO_LOG("unload model success, model Id is %u", modelId_); + INFO_LOG("unload model success, model Id is %u", modelId_); } diff --git a/amexec/src/sample_process.cpp b/amexec/src/sample_process.cpp index a4f0143..7af4a7a 100755 --- a/amexec/src/sample_process.cpp +++ b/amexec/src/sample_process.cpp @@ -17,6 +17,11 @@ using namespace std; extern bool g_isDevice; extern bool f_isTXT; extern int loop; +extern int32_t device; +extern bool is_debug; +extern bool is_profi; +extern bool is_dump; + SampleProcess::SampleProcess() :deviceId_(0), context_(nullptr), stream_(nullptr) { @@ -30,15 +35,31 @@ SampleProcess::~SampleProcess() Result SampleProcess::InitResource() { // ACL init - const char *aclConfigPath = ""; - aclError ret = aclInit(nullptr); + aclError ret; + const char *aclConfigPath = "acl.json"; + if (is_profi == true){ + ret = aclInit(aclConfigPath); + } else + { + ret = aclInit(nullptr); + } if (ret != ACL_ERROR_NONE) { +/* if (is_debug || is_profi){ + if (remove("acl.json")==0){ + INFO_LOG("delete acl.json success"); + } + else{ + ERROR_LOG("delete acl.json failed"); + } + } +*/ ERROR_LOG("acl init failed"); return FAILED; } INFO_LOG("acl init success"); // open device + deviceId_ = device; ret = aclrtSetDevice(deviceId_); if (ret != ACL_ERROR_NONE) { ERROR_LOG("acl open device %d failed", deviceId_); @@ -71,6 +92,17 @@ Result SampleProcess::InitResource() } g_isDevice = (runMode == ACL_DEVICE); INFO_LOG("get run mode success"); + +/* // dump init + if (is_dump == true){ + ret = aclmdlInitDump(); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("dump init failed"); + return FAILED; + } + INFO_LOG("dump init success"); + } +*/ return SUCCESS; } @@ -83,9 +115,6 @@ Result SampleProcess::Process(map& params, vector& input_fi const char* outfmt = params['f'].c_str(); const char* fmt_TXT = "TXT"; f_isTXT = (strcmp(outfmt,fmt_TXT)==0); - const char* dumpConf = params['d'].c_str(); - const char* profConf = params['p'].c_str(); - const char* dymBatch = params['y'].c_str(); std::string modelPath = params['m'].c_str(); std::string modelName = Utils::modelName(modelPath); @@ -104,62 +133,98 @@ Result SampleProcess::Process(map& params, vector& input_fi ERROR_LOG("create model description failed"); return FAILED; } - + /* // dump init + if (is_dump){ + const char *aclConfigPath = "acl.json"; + ret = aclmdlSetDump(aclConfigPath); + if (ret != SUCCESS) { + ERROR_LOG("dump init failed"); + return FAILED; + } + INFO_LOG("dump init success"); + } +*/ + if (is_debug){ + ret = processModel.PrintDesc(); + if (ret != SUCCESS) { + ERROR_LOG("print model descrtption failed"); + return FAILED; + } + } ret = processModel.CreateOutput(); if (ret != SUCCESS) { ERROR_LOG("create model output failed"); return FAILED; } - vector picDevBuffer(input_files.size(), nullptr); - for (size_t index = 0; index < input_files.size(); ++index) { - INFO_LOG("start to process file:%s", input_files[index].c_str()); - // model process - uint32_t devBufferSize; - picDevBuffer[index] = Utils::GetDeviceBufferOfFile(input_files[index], devBufferSize); - if (picDevBuffer[index] == nullptr) { - ERROR_LOG("get pic device buffer failed,index is %zu", index); - return FAILED; - } - - ret = processModel.CreateInput(picDevBuffer[index], devBufferSize); + if (input_files.empty() == 1) { + ret = processModel.CreateZeroInput(); if (ret != SUCCESS) { ERROR_LOG("model create input failed"); - for (size_t i = 0; i < index; i++) { - aclrtFree(picDevBuffer[i]); - } return FAILED; } } - // loop end - for (size_t t = 0; t < loop; ++t){ - gettimeofday(&begin,NULL); - ret = processModel.Execute(); - gettimeofday(&end,NULL); - inference_time[t] = 1000*(end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec)/1000.000; - std::cout << "Inference time: "< picDevBuffer(input_files.size(), nullptr); + for (size_t index = 0; index < input_files.size(); ++index) { + INFO_LOG("start to process file:%s", input_files[index].c_str()); + // model process + uint32_t devBufferSize; + picDevBuffer[index] = Utils::GetDeviceBufferOfFile(input_files[index], devBufferSize); + if (picDevBuffer[index] == nullptr) { + ERROR_LOG("get pic device buffer failed,index is %zu", index); return FAILED; } - processModel.OutputModelResult(output_path,modelName,t); + + ret = processModel.CreateInput(picDevBuffer[index], devBufferSize); + for (size_t i = 0; i < index; i++) { + aclrtFree (picDevBuffer[i]); + } + if (ret != SUCCESS) { + ERROR_LOG("model create input failed"); + return FAILED; + } + } + } + + // loop end + for (size_t t = 0; t < loop; ++t) { + gettimeofday(&begin, NULL); + ret = processModel.Execute(); + gettimeofday(&end, NULL); + inference_time[t] = 1000 * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / 1000.000; + std::cout << "Inference time: " << inference_time[t] << "ms" << endl; + if (ret != SUCCESS) { + ERROR_LOG("model execute failed"); +// for (size_t i = 0; i < input_files.size(); i++) { +// aclrtFree(picDevBuffer[i]); +// } + return FAILED; + } + processModel.OutputModelResult(output_path, modelName, t); } double infer_time_ave = Utils::InferenceTimeAverage(inference_time, loop); printf("Inference average time: %f ms\n", infer_time_ave); - if (loop > 1){ - double infer_time_ave_without_first = Utils::InferenceTimeAverageWithoutFirst(inference_time, loop); - printf("Inference average time without first time: %f ms\n", infer_time_ave_without_first); - } + if (loop > 1) { + double infer_time_ave_without_first = Utils::InferenceTimeAverageWithoutFirst(inference_time, loop); + printf("Inference average time without first time: %f ms\n", infer_time_ave_without_first); + } processModel.DestroyInput(); - // release model input buffer - for (size_t i = 0; i < input_files.size(); i++) { - aclrtFree(picDevBuffer[i]); + if (is_dump || is_profi){ + if (remove("acl.json")==0){ + INFO_LOG("delete acl.json success"); + } + else{ + ERROR_LOG("delete acl.json failed"); + } } - + + // release model input buffer +// for (size_t i = 0; i < input_files.size(); i++) { +// aclrtFree(picDevBuffer[i]); +// } + return SUCCESS; } @@ -185,11 +250,19 @@ void SampleProcess::DestroyResource() INFO_LOG("end to destroy context"); ret = aclrtResetDevice(deviceId_); - if (ret != ACL_ERROR_NONE) { + if (ret != ACL_ERROR_NONE) { ERROR_LOG("reset device failed"); } INFO_LOG("end to reset device is %d", deviceId_); - + +/* if (is_dump){ + ret = aclmdlFinalizeDump(); + if (ret != ACL_ERROR_NONE) { + ERROR_LOG("finalize dump failed"); + } + } + INFO_LOG("end to finalize dump"); +*/ ret = aclFinalize(); if (ret != ACL_ERROR_NONE) { ERROR_LOG("finalize acl failed"); diff --git a/amexec/src/utils.cpp b/amexec/src/utils.cpp index 97f8947..fc0dc62 100755 --- a/amexec/src/utils.cpp +++ b/amexec/src/utils.cpp @@ -15,7 +15,10 @@ using namespace std; extern bool g_isDevice; extern bool f_isTXT; - +extern int32_t device; +extern bool is_profi; +extern bool is_dump; + void* Utils::ReadBinFile(std::string fileName, uint32_t &fileSize) { std::ifstream binFile(fileName, std::ifstream::binary); @@ -94,17 +97,37 @@ void* Utils::GetDeviceBufferOfFile(std::string fileName, uint32_t &fileSize) void Utils::SplitString(std::string& s, std::vector& v, char c) { - std::string::size_type pos1, pos2; - pos2 = s.find(c); - pos1 = 0; - while(std::string::npos != pos2) - { - v.push_back(s.substr(pos1, pos2-pos1)); - pos1 = pos2 + 1; - pos2 = s.find(c, pos1); - } - if(pos1 != s.length()) - v.push_back(s.substr(pos1)); + std::string::size_type pos1, pos2; + pos2 = s.find(c); + pos1 = 0; + while(std::string::npos != pos2) + { + std::string s1 = s.substr(pos1, pos2-pos1); + size_t n = s1.find_last_not_of(" \r\n\t"); + if (n != string::npos) { + s1.erase(n + 1, s.size() - n); + } + n = s1.find_first_not_of(" \r\n\t"); + if (n != string::npos) { + s1.erase(0, n); + } + v.push_back(s1); + pos1 = pos2 + 1; + pos2 = s.find(c, pos1); + } + if(pos1 != s.length()) + { + std::string s1 = s.substr(pos1); + size_t n = s1.find_last_not_of(" \r\n\t"); + if (n != string::npos) { + s1.erase(n + 1, s.size() - n); + } + n = s1.find_first_not_of(" \r\n\t"); + if (n != string::npos) { + s1.erase(0, n); + } + v.push_back(s1); + } } int Utils::str2num(char *str) @@ -170,8 +193,10 @@ void Utils::printHelpLetter() cout<< " --output Output path(User needs to have permission to create directories)" << endl; cout<< " --outfmt Output file format (TXT or BIN)" << endl; cout<< " --loop loop time(must in 1 to 100)" << endl; - cout<< " --dumpConf dump configure file path (Do not support now)" << endl; - cout<< " --profConf profiling configure file path (Do not support now)" << endl; + cout<< " --dump Enable dump (true or false)" << endl; + cout<< " --profiler Enable profiler (true or false)" << endl; + cout<< " --device Designated the device ID(must in 0 to 255)" << endl; + cout<< " --debug Debug switch,print model information (true or false)" << endl; cout<< " --dymBatch dynamic batch (Do not support now)" << endl << endl << endl; @@ -205,3 +230,73 @@ double Utils::InferenceTimeAverageWithoutFirst(double *x, int len) return sum / (len - 1); } + +void Utils::ProfilerJson(bool isprof, map& params) +{ + if (isprof){ + std::string out_path = params['o'].c_str(); + std::string out_profiler_path = out_path + "/profiler"; + ofstream outstr("acl.json", ios::out); + outstr << "{\n\"profiler\": {\n \"switch\": \"on\",\n \"device_id\": \""; + outstr << device << "\",\n \"result_path\": \"" << out_profiler_path << "\",\n "; + outstr << "\"ai_core_metrics\": \"\"}\n}"; + //outstr << "\"ai_core_metrics\": \"aicorePipelineStall\"}\n}"; + //outstr <<"}]n}"; + outstr.close(); + + //mkdir profiler output dir + const char* temp_s = out_path.c_str(); + if (NULL == opendir(temp_s)){ + mkdir(temp_s,0775); + } + const char* temp_s1 = out_profiler_path.c_str(); + if (NULL == opendir(temp_s1)){ + mkdir(temp_s1,0775); + } + /*{ + "profiler": { + "switch": "on", + "device_id": "all", + "result_path": "/home/HwHiAiUser", + "ai_core_metrics": "aicorePipelineStall" + } + } + */ + } +} + +void Utils::DumpJson(bool isdump, map& params) +{ + if (is_dump){ + std::string modelPath = params['m'].c_str(); + std::string modelName = Utils::modelName(modelPath); + std::string out_path = params['o'].c_str(); + std::string out_dump_path = out_path + "/dump"; + ofstream outstr("acl.json", ios::out); + outstr << "{\n\"dump\": {\n \"dump_path\": \""; + outstr << out_dump_path << "\",\n "; + outstr << "\"dump_mode\": \"output\",\n \"dump_list\": [{\n "; + outstr << " \"model_name\": \"" << modelName << "\",\n }]\n"; + outstr << " }\n}"; + outstr.close(); + + //mkdir dump output dir + const char* temp_s = out_path.c_str(); + if (NULL == opendir(temp_s)){ + mkdir(temp_s,0775); + } + const char* temp_s1 = out_dump_path.c_str(); + if (NULL == opendir(temp_s1)){ + mkdir(temp_s1,0775); + } + // { + // "dump": { + // "dump_path": "output_path", + // "dump_mode": "output", + // "dump_list": [{ + // "model_name": "model_name", + // }] + // } + // } + } +}