This patch adds apptest for multiple inferences.
Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
install_dir : join_paths(ne_bindir, 'apptests')
)
+executable ('apptest_tvn_triv2_aging',
+ 'tvn_triv2_aging.cc',
+ include_directories : ne_apptest_inc,
+ dependencies : ne_test_utils_dep,
+ link_with : ne_library_shared,
+ install : true,
+ install_rpath : ne_libdir,
+ install_dir : join_paths(ne_bindir, 'apptests')
+)
+
# npumgr is available on tizen env.
if target_platform == 'tizen'
subdir('npumgr')
Tester tester;
char *dir;
int status;
+ int index;
- status = tester.parseArgs (argc, argv, &dir, "[model dir]");
- if (status == test_ret_skipped || dir == nullptr)
+ status = tester.parseArgs (argc, argv, "model_path", &index);
+ if (status == test_ret_skipped || index < 0)
goto skip;
- else if (status != test_ret_success)
- goto err;
+ dir = argv[index];
/** initialize triv2 device */
status = tester.init (dir);
if (status < test_ret_success)
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2020 Samsung Electronics
+ * Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file tvn_triv2_aging.cc
+ * @date 23 June 2021
+ * @brief AppTest to test multiple inferences for TRIV2 device
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include <ne_test_utils.h>
+
+#define NPU_TIMEOUT_MS 5000
+
+using namespace std;
+
+/** @brief C++ class to describe how to use npu-engine library */
+class Tester : public UtilTRIV2 {
+ public:
+ Tester () : model_id_ (0), num_iter_ (0) {}
+
+ /** @brief initilize the device handle */
+ int init (string model_dir, string num_dir) {
+ if (model_dir == "" || num_dir == "")
+ return -EINVAL;
+
+ errno = 0;
+ num_iter_ = strtoul (num_dir.c_str (), NULL, 10);
+ if (errno != 0)
+ return -errno;
+
+ string model_path = model_dir + "/model.tvn";
+ npubin_meta *meta = getNPUmodel_metadata (model_path.c_str (), false);
+ if (meta == nullptr)
+ return -EINVAL;
+
+ uint32_t tops = NPU_VERSION_TOPS (meta->npu_version);
+ free (meta);
+
+ int status = UtilTRIV2::init (tops);
+ if (status != test_ret_success) {
+ cerr << "Failed to initialize\n";
+ return status;
+ }
+
+ return UtilTRIV2::loadModel (model_dir, &model_id_, NPU_PRIORITY_MID,
+ NPU_TIMEOUT_MS);
+ }
+
+ /** @brief run the inference */
+ int run () {
+ if (model_id_ == 0)
+ return test_ret_failure;
+
+ int req_id = UtilTRIV2::createRequest (model_id_);
+ if (req_id < 0)
+ return req_id;
+
+ for (uint32_t i = 0; i < num_iter_; i++)
+ UtilTRIV2::submitRequest (model_id_);
+
+ UtilTRIV2::removeRequest (req_id);
+ return wait () == num_iter_ ? test_ret_success : test_ret_failure;
+ }
+
+ private:
+ uint32_t model_id_;
+ uint32_t num_iter_;
+};
+
+/** @brief apptest main */
+int
+main (int argc, char **argv) {
+ const char *help = "model_dir num_iterations";
+ Tester tester;
+ int status;
+ int index;
+
+ status = tester.parseArgs (argc, argv, help, &index);
+ if (status == test_ret_skipped || index < 0)
+ goto skip;
+
+ if (argc < index + 2) {
+ cerr << "Need additional argument..\n";
+ tester.printUsage (argv[0], help);
+ goto skip;
+ }
+
+ /** initialize triv2 device */
+ status = tester.init (argv[index], argv[index + 1]);
+ if (status < test_ret_success)
+ goto err;
+
+ /** run the inference with the device */
+ status = tester.run ();
+ if (status < test_ret_success)
+ goto err;
+
+ cerr << "[APPTEST] " << argv[0] << ": PASSED\n";
+ return 0;
+
+err:
+ cerr << "[APPTEST] " << argv[0] << ": FAILED (" << status << ")\n";
+ return status;
+
+skip:
+ cerr << "[APPTEST] " << argv[0] << ": SKIPPED\n";
+ return 0;
+}
Tester tester;
char *dir_str;
int status;
+ int index;
std::ios_base::fmtflags f (cerr.flags ());
- status = tester.parseArgs (argc, argv, &dir_str, "[models' dir]");
- if (status == test_ret_skipped || dir_str == nullptr) {
+ status = tester.parseArgs (argc, argv, "models_path", &index);
+ if (status == test_ret_skipped || index < 0) {
cerr << "[APPTEST] " << argv[0] << ": SKIPPED\n";
return 0;
- } else if (status != test_ret_success) {
- cerr << "[APPTEST] " << argv[0] << ": FAILED (" << status << ")\n";
- return status;
}
+ dir_str = argv[index];
DIR *d = opendir (dir_str);
if (!d) {
cerr << "Failed to open " << dir_str << "\n";
Tester tester;
char *dir;
int status;
+ int index;
- status = tester.parseArgs (argc, argv, &dir, "[models' dir]");
- if (status == test_ret_skipped || dir == nullptr)
+ status = tester.parseArgs (argc, argv, "models_path", &index);
+ if (status == test_ret_skipped || index < 0)
goto skip;
- else if (status != test_ret_success)
- goto err;
+ dir = argv[index];
/** initialize triv2 device */
status = tester.init (dir);
if (status < test_ret_success)
Tester tester;
char *dir;
int status;
+ int index;
- status = tester.parseArgs (argc, argv, &dir, "[model dir]");
- if (status == test_ret_skipped || dir == nullptr)
+ status = tester.parseArgs (argc, argv, "model_path", &index);
+ if (status == test_ret_skipped || index < 0)
goto skip;
else if (status != test_ret_success)
goto err;
+ dir = argv[index];
/** initialize triv2 device */
status = tester.init (dir);
if (status < test_ret_success)
Tester tester;
char *xml_file;
int status;
+ int index;
- status = tester.parseArgs (argc, argv, &xml_file, "[.xml file]");
- if (status == test_ret_skipped || xml_file == nullptr)
+ status = tester.parseArgs (argc, argv, "xml_file_path", &index);
+ if (status == test_ret_skipped || index < 0)
goto skip;
- else if (status != test_ret_success)
- goto err;
+ xml_file = argv[index];
/** initialize triv2 device */
status = tester.init (xml_file);
if (status < test_ret_success)
/** @brief device instance cleanup */
void
UtilTrinity::clear () {
+ models_.clear ();
+
if (dev_ != nullptr) {
unregisterNPUmodel_all (dev_);
putNPUdevice (dev_);
dev_ = nullptr;
}
-
- models_.clear ();
}
/** @brief initialize trinity device and get the device handle */
}
/** @brief parse/set arguments and get working directory */
int
-UtilTrinity::parseArgs (int argc, char **argv, char **param,
- const char *param_str) {
+UtilTrinity::parseArgs (int argc, char **argv, const char *param_str,
+ int *index) {
int c;
+ if (index != nullptr)
+ *index = -1;
+
optind = 0;
opterr = 0;
while ((c = getopt (argc, argv, "d:n:p:tmsho")) != -1) {
else
std::cerr << "Unknown flag: " << c;
std::cerr << std::endl;
- printUsage (argv[0], param_str);
- return test_ret_failure;
case 'h':
printUsage (argv[0], param_str);
return test_ret_skipped;
}
}
- if (optind < argc)
- *param = argv[optind];
- else
- *param = nullptr;
+ if (index != nullptr && optind < argc)
+ *index = optind;
return test_ret_success;
}
if (status != 0)
goto free_meta;
- model = new UtilModel;
+ model = new UtilModel (dev_);
model->setMetadata (meta);
model->setDirpath (dirpath);
model->setModelID (model_id);
fclose (dump_fp);
}
}
+ } else {
+ free (output->bufs[idx].addr);
}
-
- free (output->bufs[idx].addr);
}
std::unique_lock<std::mutex> lock (m_);
/** @brief callback without verification */
void
UtilTrinity::callback (output_buffers *output, int req_id, void *data) {
- for (uint32_t idx = 0; idx < output->num_buffers; idx++)
- free (output->bufs[idx].addr);
+ UtilModel *model = static_cast<UtilModel *> (data);
+
+ if (model == nullptr) {
+ for (uint32_t idx = 0; idx < output->num_buffers; idx++)
+ free (output->bufs[idx].addr);
+ }
std::unique_lock<std::mutex> lock (m_);
done_++;
}
if (sync) {
- output_buffers output;
+ output_buffers *cb_output;
if (model) {
+ cb_output = model->getOutput ();
status =
- runNPU_sync (dev_, model->getModelID (), model->getInput (), &output);
+ runNPU_model (dev_, model->getModelID (), NPU_INFER_BLOCKING,
+ model->getInput (), model->getOutput (), NULL, NULL);
} else {
/* TODO: revise this when TRIA is implemented */
input_buffers input;
if (status != 0)
return status;
+ output_buffers output;
+ cb_output = &output;
status = runNPU_sync (dev_, 0, &input, &output);
cleanNPU_inputBuffers (dev_, &input);
}
total_++;
}
- cb (&output, 0, cb_data);
+ cb (cb_output, 0, cb_data);
}
} else {
if (model) {
- status = runNPU_async (dev_, model->getModelID (), model->getInput (), cb,
- NULL, cb_data, NPUASYNC_WAIT);
+ status =
+ runNPU_model (dev_, model->getModelID (), NPU_INFER_NON_BLOCKING,
+ model->getInput (), model->getOutput (), cb, cb_data);
} else {
/* TODO: revise this when TRIA is implemented */
input_buffers input;
return status;
}
+/** @brief create request */
+int
+UtilTrinity::createRequest (uint32_t model_id) {
+ UtilModel *model = findModel (model_id);
+ int status, req_id;
+
+ if (model == nullptr)
+ return -ENOENT;
+
+ status = createNPU_request (dev_, model_id, &req_id);
+ if (status != 0)
+ return status;
+
+ status = setNPU_requestData (dev_, req_id, model->getInput (), nullptr,
+ model->getOutput (), nullptr);
+ if (status != 0) {
+ removeNPU_request (dev_, req_id);
+ return status;
+ }
+
+ return req_id;
+}
+
+/** @brief submit request */
+int
+UtilTrinity::submitRequest (int req_id) {
+ UtilModel *model;
+ uint32_t model_id;
+ int status;
+
+ status = getNPU_requestModel (dev_, req_id, &model_id);
+ if (status != 0)
+ return status;
+
+ model = findModel (model_id);
+ if (model == nullptr)
+ return -ENOENT;
+
+ status = submitNPU_request (dev_, req_id);
+ if (status == 0) {
+ total_++;
+ UtilTrinity::callbackVerify (model->getOutput (), req_id,
+ static_cast<void *> (model));
+ }
+
+ return status;
+}
+
+/** @brief remove request */
+int
+UtilTrinity::removeRequest (int req_id) {
+ return removeNPU_request (dev_, req_id);
+}
+
/** @brief run inference with the given model id (default sync) */
int
UtilTrinity::run (uint32_t model_id) {
int
UtilTRIV2::prepare_model (UtilModel *model) {
input_buffers *input = model->getInput ();
+ output_buffers *output = model->getOutput ();
+
npubin_meta *meta = model->getMetadata ();
std::string dirpath = model->getDirpath ();
input->bufs[idx].type = BUFFER_FILE;
}
- return 0;
+ output->num_buffers = meta->output_seg_num;
+
+ for (uint32_t idx = 0; idx < meta->output_seg_num; idx++) {
+ const char *output_path = model->getOutputPath (idx);
+
+ output->bufs[idx].size = get_file_size (output_path);
+ output->bufs[idx].type = BUFFER_MAPPED;
+ }
+
+ return allocNPU_genericBuffers (dev_, output);
}
/** @brief utility to access test model */
class UtilModel {
public:
- UtilModel () : meta_ (nullptr), model_id_ (0) {
+ UtilModel (npudev_h dev) : dev_ (dev), meta_ (nullptr), model_id_ (0) {
memset (&input_, '\x00', sizeof (input_buffers));
+ memset (&output_, '\x00', sizeof (output_buffers));
}
~UtilModel () {
+ if (output_.num_buffers > 0)
+ cleanNPU_genericBuffers (dev_, &output_);
+
if (meta_)
free (meta_);
}
std::string &getDirpath () { return dirpath_; }
uint32_t getModelID () { return model_id_; }
input_buffers *getInput () { return &input_; }
+ output_buffers *getOutput () { return &output_; }
private:
+ npudev_h dev_;
+
npubin_meta *meta_;
uint32_t model_id_;
std::string dirpath_;
input_buffers input_;
+ output_buffers output_;
+
std::vector<std::string> inpath_;
std::vector<std::string> outpath_;
};
int init (uint32_t tops = default_tops);
void clear ();
void printUsage (const char *prog_name, const char *param_str = nullptr);
- int parseArgs (int argc, char **argv, char **param,
- const char *param_str = nullptr);
+ int parseArgs (int argc, char **argv, const char *param_str = nullptr,
+ int *index = nullptr);
int loadModel (std::string dirpath, uint32_t *model_id,
npu_priority priority = NPU_PRIORITY_MID,
uint32_t timeout = 5000);
+ int createRequest (uint32_t model_id);
+ int submitRequest (int req_id);
+ int removeRequest (int req_id);
+
int run (uint32_t model_id);
int run (uint32_t model_id, bool sync);
int runAll ();