#include #include #include "common/util.h" #include "snpemodel.h" void PrintErrorStringAndExit() { const char* const errStr = zdl::DlSystem::getLastErrorString(); std::cerr << zdl::DlSystem::getLastErrorString() << std::endl; std::exit(EXIT_FAILURE); } SNPEModel::SNPEModel(const char *path, float *output, size_t output_size) { #ifdef QCOM assert(zdl::SNPE::SNPEFactory::isRuntimeAvailable(zdl::DlSystem::Runtime_t::GPU)); #endif size_t model_size; model_data = (uint8_t *)read_file(path, &model_size); assert(model_data); // load model std::unique_ptr container = zdl::DlContainer::IDlContainer::open(model_data, model_size); if (!container) { PrintErrorStringAndExit(); } printf("loaded model with size: %u\n", model_size); // create model runner zdl::SNPE::SNPEBuilder snpeBuilder(container.get()); while (!snpe) { #ifdef QCOM snpe = snpeBuilder.setOutputLayers({}) .setRuntimeProcessor(zdl::DlSystem::Runtime_t::GPU) .setUseUserSuppliedBuffers(true) .setPerformanceProfile(zdl::DlSystem::PerformanceProfile_t::HIGH_PERFORMANCE) .build(); #else snpe = snpeBuilder.setOutputLayers({}) .setUseUserSuppliedBuffers(true) .setPerformanceProfile(zdl::DlSystem::PerformanceProfile_t::HIGH_PERFORMANCE) .build(); #endif if (!snpe) std::cerr << zdl::DlSystem::getLastErrorString() << std::endl; } // get input and output names const auto &strListi_opt = snpe->getInputTensorNames(); if (!strListi_opt) throw std::runtime_error("Error obtaining Input tensor names"); const auto &strListi = *strListi_opt; //assert(strListi.size() == 1); const char *input_tensor_name = strListi.at(0); const auto &strListo_opt = snpe->getOutputTensorNames(); if (!strListo_opt) throw std::runtime_error("Error obtaining Output tensor names"); const auto &strListo = *strListo_opt; assert(strListo.size() == 1); const char *output_tensor_name = strListo.at(0); printf("model: %s -> %s\n", input_tensor_name, output_tensor_name); zdl::DlSystem::UserBufferEncodingFloat userBufferEncodingFloat; zdl::DlSystem::IUserBufferFactory& ubFactory = zdl::SNPE::SNPEFactory::getUserBufferFactory(); // create input buffer { const auto &inputDims_opt = snpe->getInputDimensions(input_tensor_name); const zdl::DlSystem::TensorShape& bufferShape = *inputDims_opt; std::vector strides(bufferShape.rank()); strides[strides.size() - 1] = sizeof(float); size_t product = 1; for (size_t i = 0; i < bufferShape.rank(); i++) product *= bufferShape[i]; size_t stride = strides[strides.size() - 1]; for (size_t i = bufferShape.rank() - 1; i > 0; i--) { stride *= bufferShape[i]; strides[i-1] = stride; } printf("input product is %u\n", product); inputBuffer = ubFactory.createUserBuffer(NULL, product*sizeof(float), strides, &userBufferEncodingFloat); inputMap.add(input_tensor_name, inputBuffer.get()); } // create output buffer { std::vector outputStrides = {output_size * sizeof(float), sizeof(float)}; outputBuffer = ubFactory.createUserBuffer(output, output_size * sizeof(float), outputStrides, &userBufferEncodingFloat); outputMap.add(output_tensor_name, outputBuffer.get()); } } void SNPEModel::addRecurrent(float *state, int state_size) { recurrentBuffer = this->addExtra(state, state_size, 2); } void SNPEModel::addDesire(float *state, int state_size) { desireBuffer = this->addExtra(state, state_size, 1); } std::unique_ptr SNPEModel::addExtra(float *state, int state_size, int idx) { // get input and output names const auto &strListi_opt = snpe->getInputTensorNames(); if (!strListi_opt) throw std::runtime_error("Error obtaining Input tensor names"); const auto &strListi = *strListi_opt; const char *input_tensor_name = strListi.at(idx); printf("adding index %d: %s\n", idx, input_tensor_name); zdl::DlSystem::UserBufferEncodingFloat userBufferEncodingFloat; zdl::DlSystem::IUserBufferFactory& ubFactory = zdl::SNPE::SNPEFactory::getUserBufferFactory(); std::vector retStrides = {state_size * sizeof(float), sizeof(float)}; auto ret = ubFactory.createUserBuffer(state, state_size * sizeof(float), retStrides, &userBufferEncodingFloat); inputMap.add(input_tensor_name, ret.get()); return ret; } void SNPEModel::execute(float *net_input_buf) { assert(inputBuffer->setBufferAddress(net_input_buf)); if (!snpe->execute(inputMap, outputMap)) { PrintErrorStringAndExit(); } }