Skip to content

Commit

Permalink
[onert] Support model file loading from model path
Browse files Browse the repository at this point in the history
This commit updates API to support model file loading from model path.

ONE-DCO-1.0-Signed-off-by: Hyeongseok Oh <[email protected]>
  • Loading branch information
hseok-oh committed Dec 18, 2024
1 parent 5044bb4 commit b02adc5
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 118 deletions.
10 changes: 5 additions & 5 deletions runtime/onert/api/nnfw/include/nnfw.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,16 @@ NNFW_STATUS nnfw_create_session(nnfw_session **session);
NNFW_STATUS nnfw_close_session(nnfw_session *session);

/**
* @brief Load model from nnpackage file or directory
* @brief Load model from model file or nnpackage directory
*
* The length of \p package_file_path must not exceed 1024 bytes including zero at the end.
* The length of \p file_path must not exceed 1024 bytes including zero at the end.
*
* @param[in] session nnfw_session loading the given nnpackage file/dir
* @param[in] package_file_path Path to the nnpackage file or unzipped directory to be loaded
* @param[in] session nnfw_session loading the given file/dir
* @param[in] file_path Path to the model file or nnpackage directory to be loaded
*
* @return @c NNFW_STATUS_NO_ERROR if successful
*/
NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *package_file_path);
NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *file_path);

/**
* @brief Apply i-th input's tensor info to resize input tensor
Expand Down
8 changes: 4 additions & 4 deletions runtime/onert/api/nnfw/src/nnfw_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ NNFW_STATUS nnfw_close_session(nnfw_session *session)
/*
* Load model from nnpackage file or directory
*
* @param session nnfw_session loading the given nnpackage file/dir
* @param package_file_path path to the nnpackage file or unzipped directory to be loaded
* @param session nnfw_session loading the given file/dir
* @param file_path path to the model file or nnpackage directory to be loaded
*
* @return NNFW_STATUS_NO_ERROR if successful
*/
NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *pacakge_file_path)
NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *file_path)
{
NNFW_RETURN_ERROR_IF_NULL(session);
return session->load_model_from_nnpackage(pacakge_file_path);
return session->load_model_from_path(file_path);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion runtime/onert/api/nnfw/src/nnfw_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ NNFW_STATUS nnfw_load_circle_from_buffer(nnfw_session *session, uint8_t *buffer,
NNFW_STATUS nnfw_load_model_from_modelfile(nnfw_session *session, const char *file_path)
{
NNFW_RETURN_ERROR_IF_NULL(session);
return session->load_model_from_modelfile(file_path);
return session->load_model_from_path(file_path);
}

NNFW_STATUS nnfw_train_export_circleplus(nnfw_session *session, const char *path)
Expand Down
196 changes: 90 additions & 106 deletions runtime/onert/api/nnfw/src/nnfw_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -301,150 +301,134 @@ NNFW_STATUS nnfw_session::load_circle_from_buffer(uint8_t *buffer, size_t size)
return NNFW_STATUS_NO_ERROR;
}

NNFW_STATUS nnfw_session::load_model_from_modelfile(const char *model_file_path)
NNFW_STATUS nnfw_session::load_model_from_path(const char *path)
{
if (!isStateInitialized())
return NNFW_STATUS_INVALID_STATE;

if (!model_file_path)
if (!path)
{
std::cerr << "Model file path is null." << std::endl;
std::cerr << "Path is null." << std::endl;
return NNFW_STATUS_UNEXPECTED_NULL;
}

if (!null_terminating(path, MAX_PATH_LENGTH))
{
std::cerr << "Path is too long" << std::endl;
return NNFW_STATUS_ERROR;
}

try
{
std::filesystem::path filename{model_file_path};
if (!filename.has_extension())
std::filesystem::path filename{path};
if (filename.has_extension())
{
std::cerr << "Invalid model file path. Please use file with extension." << std::endl;
return NNFW_STATUS_ERROR;
std::string model_type = filename.extension().string().substr(1); // + 1 to exclude dot
return loadModelFile(filename, model_type);
}

std::string model_type = filename.extension().string().substr(1); // + 1 to exclude dot
return loadModelFile(filename, model_type);
return loadNNPackage(filename);
}
catch (const std::exception &e)
{
std::cerr << "Error during model loading : " << e.what() << std::endl;
return NNFW_STATUS_ERROR;
}

return NNFW_STATUS_NO_ERROR;
}

NNFW_STATUS nnfw_session::load_model_from_nnpackage(const char *package_dir)
NNFW_STATUS nnfw_session::loadNNPackage(const std::filesystem::path &package_dir)
{
if (!isStateInitialized())
return NNFW_STATUS_INVALID_STATE;

if (!package_dir)
// TODO : add support for zipped package file load
if (!std::filesystem::is_directory(package_dir))
{
std::cerr << "package_dir is null." << std::endl;
return NNFW_STATUS_UNEXPECTED_NULL;
}

if (!null_terminating(package_dir, MAX_PATH_LENGTH))
{
std::cerr << "nnpackage path is too long" << std::endl;
std::cerr << "invalid path: " << package_dir << std::endl;
return NNFW_STATUS_ERROR;
}

try
{
// TODO : add support for zipped package file load
const std::filesystem::path package_path(package_dir);
if (!std::filesystem::is_directory(package_path))
{
std::cerr << "invalid nnpackage directory: " << package_path << std::endl;
return NNFW_STATUS_ERROR;
}

const auto manifest_file_name = package_path / "metadata/MANIFEST";
std::ifstream mfs(manifest_file_name);
const auto manifest_file_name = package_dir / "metadata/MANIFEST";
std::ifstream mfs(manifest_file_name);

// extract the filename of the first(index 0) model
// e.g. In MANIFEST file, { "models" : [ "firstmodel.tflite", "2nd.tflite" ] }
Json::Value root;
mfs >> root;
const Json::Value &models = root["models"];
const Json::Value &model_types = root["model-types"];
const Json::Value &configs = root["configs"];
// extract the filename of the first(index 0) model
// e.g. In MANIFEST file, { "models" : [ "firstmodel.tflite", "2nd.tflite" ] }
Json::Value root;
mfs >> root;
const Json::Value &models = root["models"];
const Json::Value &model_types = root["model-types"];
const Json::Value &configs = root["configs"];

if (!configs.empty() && !configs[0].empty())
{
const auto filepath = package_path / "metadata" / configs[0].asString();
if (!configs.empty() && !configs[0].empty())
{
const auto filepath = package_dir / "metadata" / configs[0].asString();

onert::util::CfgKeyValues keyValues;
if (loadConfigure(filepath.string(), keyValues))
{
onert::util::setConfigKeyValues(keyValues);
}
}
_nnpkg = std::make_shared<onert::ir::NNPkg>();
auto num_models = models.size();
if (num_models == 0 || (num_models - 1) > onert::ir::ModelIndex::max())
onert::util::CfgKeyValues keyValues;
if (loadConfigure(filepath.string(), keyValues))
{
std::cerr << "Invalid model size - " << std::to_string(num_models) << std::endl;
return NNFW_STATUS_ERROR;
onert::util::setConfigKeyValues(keyValues);
}
}
_nnpkg = std::make_shared<onert::ir::NNPkg>();
auto num_models = models.size();
if (num_models == 0 || (num_models - 1) > onert::ir::ModelIndex::max())
{
std::cerr << "Invalid model size - " << std::to_string(num_models) << std::endl;
return NNFW_STATUS_ERROR;
}

// Not support backend mapping to operator index for multiple models yet
// TODO Support this
if (num_models > 1 && _coptions->manual_scheduler_options.index_to_backend.size() != 0)
{
std::cerr << "Cannot set backend to operator index for multiple models" << std::endl;
return NNFW_STATUS_ERROR;
}
// Not support backend mapping to operator index for multiple models yet
// TODO Support this
if (num_models > 1 && _coptions->manual_scheduler_options.index_to_backend.size() != 0)
{
std::cerr << "Cannot set backend to operator index for multiple models" << std::endl;
return NNFW_STATUS_ERROR;
}

for (uint16_t i = 0; i < num_models; ++i)
{
const auto model_file_path = package_path / models[i].asString();
const auto model_type = model_types[i].asString();
auto model = loadModel(model_file_path.string(), model_type);
if (model == nullptr)
return NNFW_STATUS_ERROR;
_model_path = model_file_path; // TODO Support multiple models
model->bindKernelBuilder(_kernel_registry->getBuilder());
_nnpkg->push(onert::ir::ModelIndex{i}, std::move(model));
}
for (uint16_t i = 0; i < num_models; ++i)
{
const auto model_file_path = package_dir / models[i].asString();
const auto model_type = model_types[i].asString();
auto model = loadModel(model_file_path.string(), model_type);
if (model == nullptr)
return NNFW_STATUS_ERROR;
_model_path = model_file_path; // TODO Support multiple models
model->bindKernelBuilder(_kernel_registry->getBuilder());
_nnpkg->push(onert::ir::ModelIndex{i}, std::move(model));
}

_train_info = loadTrainingInfo(_nnpkg->primary_model());
_train_info = loadTrainingInfo(_nnpkg->primary_model());

auto toIODesc = [](std::string str) {
auto indices = nnfw::misc::split(str, ':');
if (indices.size() != 3)
{
std::cerr << "IODesc should be 3-tuple." << std::endl;
return onert::ir::IODesc{};
}
auto model_idx = static_cast<uint32_t>(std::stoi(indices.at(0)));
auto subgraph_idx = static_cast<uint32_t>(std::stoi(indices.at(1)));
auto operand_idx = static_cast<uint32_t>(std::stoi(indices.at(2)));
return onert::ir::IODesc{model_idx, subgraph_idx, operand_idx};
};
// read pkg-inputs and pkg-outputs
const Json::Value &pkg_inputs = root["pkg-inputs"];
for (uint32_t i = 0; i < pkg_inputs.size(); ++i)
_nnpkg->addInput(toIODesc(pkg_inputs[i].asString()));
const Json::Value &pkg_outputs = root["pkg-outputs"];
for (uint32_t i = 0; i < pkg_outputs.size(); ++i)
_nnpkg->addOutput(toIODesc(pkg_outputs[i].asString()));
// read model-connect
const Json::Value &fromtos = root["model-connect"];
for (uint32_t i = 0; i < fromtos.size(); ++i)
auto toIODesc = [](std::string str) {
auto indices = nnfw::misc::split(str, ':');
if (indices.size() != 3)
{
const Json::Value &tos = fromtos[i]["to"];
for (uint32_t j = 0; j < tos.size(); ++j)
_nnpkg->addEdge(toIODesc(fromtos[i]["from"].asString()), toIODesc(tos[j].asString()));
std::cerr << "IODesc should be 3-tuple." << std::endl;
return onert::ir::IODesc{};
}
auto model_idx = static_cast<uint32_t>(std::stoi(indices.at(0)));
auto subgraph_idx = static_cast<uint32_t>(std::stoi(indices.at(1)));
auto operand_idx = static_cast<uint32_t>(std::stoi(indices.at(2)));
return onert::ir::IODesc{model_idx, subgraph_idx, operand_idx};
};
// read pkg-inputs and pkg-outputs
const Json::Value &pkg_inputs = root["pkg-inputs"];
for (uint32_t i = 0; i < pkg_inputs.size(); ++i)
_nnpkg->addInput(toIODesc(pkg_inputs[i].asString()));
const Json::Value &pkg_outputs = root["pkg-outputs"];
for (uint32_t i = 0; i < pkg_outputs.size(); ++i)
_nnpkg->addOutput(toIODesc(pkg_outputs[i].asString()));
// read model-connect
const Json::Value &fromtos = root["model-connect"];
for (uint32_t i = 0; i < fromtos.size(); ++i)
{
const Json::Value &tos = fromtos[i]["to"];
for (uint32_t j = 0; j < tos.size(); ++j)
_nnpkg->addEdge(toIODesc(fromtos[i]["from"].asString()), toIODesc(tos[j].asString()));
}

_nnpkg->verify();
_state = State::MODEL_LOADED;

_nnpkg->verify();
_state = State::MODEL_LOADED;
}
catch (const std::exception &e)
{
std::cerr << "Error during model loading : " << e.what() << std::endl;
return NNFW_STATUS_ERROR;
}
return NNFW_STATUS_NO_ERROR;
}

Expand Down
4 changes: 2 additions & 2 deletions runtime/onert/api/nnfw/src/nnfw_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct nnfw_session

public:
~nnfw_session();
NNFW_STATUS load_model_from_nnpackage(const char *package_file_path);
NNFW_STATUS load_model_from_path(const char *path);
NNFW_STATUS prepare();
NNFW_STATUS run();

Expand Down Expand Up @@ -139,7 +139,6 @@ struct nnfw_session
NNFW_STATUS set_config(const char *key, const char *value);
NNFW_STATUS get_config(const char *key, char *value, size_t value_size);
NNFW_STATUS load_circle_from_buffer(uint8_t *buffer, size_t size);
NNFW_STATUS load_model_from_modelfile(const char *file_path);

//
// Experimental API
Expand Down Expand Up @@ -195,6 +194,7 @@ struct nnfw_session
uint32_t getInputSize();
uint32_t getOutputSize();
NNFW_STATUS loadModelFile(const std::string &model_file_path, const std::string &model_type);
NNFW_STATUS loadNNPackage(const std::filesystem::path &package_dir);

bool isStateInitialized();
bool isStateModelLoaded();
Expand Down

0 comments on commit b02adc5

Please sign in to comment.