This patch adds new API to get a device instance with tops info.
It tries to find any available device with the given tops.
Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
static const uint32_t default_timeout = 3000;
static const npu_priority default_priority = NPU_PRIORITY_MID;
static const npu_notimode default_notimode = NPU_INTERRUPT;
+static const uint32_t default_tops = 8; /** TODO: change to 2-TOPS when testdata is ready */
/**
* @brief Description of npu device status
/**
* @brief Returns the number of available NPU devices.
+ * @param[in] type the device type
* @return @c The number of available NPU devices.
* @note this number indicates the range of device IDs in getNPUdeviceByType ().
*/
/**
* @brief Returns the handle of the chosen NPU devices.
* @param[out] dev The NPU device handle
+ * @param[in] type the NPU device type
* @param[in] id The NPU id to get the handle. 0 <= id < getnumNPUdeviceByType().
* @return @c 0 if no error. otherwise a negative error value
* @note the caller should call putNPUdevice() to release the device handle
int getNPUdeviceByType (npudev_h *dev, dev_type type, uint32_t id);
/**
+ * @brief Returns the handle of any available device with the given type and tops.
+ * @param[out] dev The NPU device handle
+ * @param[in] type the NPU device type
+ * @param[in] tops the device's computing power (Tera Operations Per Sec)
+ * @return @c 0 if no error. otherwise a negative error value
+ * @note the caller should call putNPUdevice() to release the device handle
+ */
+int getNPUdeviceByTypeAny (npudev_h *dev, dev_type type, uint32_t tops);
+
+/**
* @brief release the NPU device instance obtained by getDevice ()
* @param[in] dev the NPU device handle
*/
}
/**
+ * @brief Returns the handle of any available device with the given type and tops.
+ * @param[out] dev The NPU device handle
+ * @param[in] type the NPU device type
+ * @param[in] tops the device's computing power (Tera Operations Per Sec)
+ * @return @c 0 if no error. otherwise a negative error value
+ * @note the caller should call putNPUdevice() to release the device handle
+ */
+int getNPUdeviceByTypeAny (npudev_h *dev, dev_type type, uint32_t tops)
+{
+ int num_devices = getnumNPUdeviceByType (type);
+
+ if (tops == 0)
+ tops = default_tops;
+
+#ifdef ENABLE_EMUL
+ if (num_devices > 0)
+ return HostHandler::getDevice (dev, type, 0);
+#else
+ for (int id = 0; id < num_devices; id++) {
+ int status = HostHandler::getDevice (dev, type, id);
+ if (status == 0) {
+ uint32_t tops_ = 0;
+ status = getNPU_tops (*dev, &tops_);
+ if (status != 0 || tops_ != tops) {
+ putNPUdevice (*dev);
+ *dev = nullptr;
+ } else {
+ return 0;
+ }
+ } else {
+ return status;
+ }
+ }
+#endif
+
+ logwarn (TAG, "No available NPU device detected");
+ return -ENODEV;
+}
+
+/**
* @brief release the NPU device instance obtained by getDevice ()
* @param[in] dev the NPU device handle
*/
)
executable ('apptest_tvn_triv2_bulk',
- 'tvn_triv2_bulk.c',
+ 'tvn_triv2_bulk.cc',
include_directories : ne_apptest_inc,
dependencies : ne_test_utils_dep,
link_with : ne_library_shared,
/** @brief initilize the device handle */
int init (std::string model_dir) {
- int status = UtilTRIV2::init ();
+ if (model_dir == "")
+ return -EINVAL;
+
+ std::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;
+++ /dev/null
-/**
- * Proprietary
- * Copyright (C) 2020 Samsung Electronics
- * Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
- */
-/**
- * @file tvn_triv2_bulk.c
- * @date 14 May 2020
- * @brief AppTest to test example visa binaries (triv2/npubinfmt v3)
- * @author Dongju Chae <dongju.chae@samsung.com>
- * @bug No known bugs except for NYI items
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <libnpuhost.h>
-#include <npubinfmt.h>
-#include <ne_test_utils.h>
-
-#define MAX_FILE_LEN 256
-#define NPU_MODEL_NAME "model.tvn"
-#define NPU_TIMEOUT_MS 5000
-
-static int enable_output_dump = 0;
-
-/** @brief compare output buffers */
-static int
-compare_output_buffers (const npubin_meta *meta, const char *base_path,
- const char *target, output_buffers *output)
-{
- char golden_path[MAX_FILE_LEN];
- char *output_data;
- off_t output_size;
- int err = 0;
- uint32_t idx;
-
- for (idx = 0; idx < output->num_buffers; idx++) {
- output_data = output->bufs[idx].addr;
- output_size = output->bufs[idx].size;
-
- snprintf (golden_path, MAX_FILE_LEN, "%s/%s/output_fmap_%d.bin",
- base_path, target, idx);
-
- err = compare_data (golden_path, output_data, output_size);
-
- if (enable_output_dump == 1) {
- char output_path[MAX_FILE_LEN];
- FILE *f;
-
- snprintf (output_path, MAX_FILE_LEN, "%s/%s/obtained_fmap_%d.bin",
- base_path, target, idx);
- f = fopen (output_path, "wb");
- if (f != NULL) {
- fwrite (output_data, output_size, 1, f);
- fclose (f);
- }
- }
-
- assert (output->bufs[idx].type == BUFFER_MAPPED);
- free (output->bufs[idx].addr);
-
- if (err != 0)
- break;
- }
-
- return err;
-}
-
-/** @brief run inference for each target visa binary (on sync mode) */
-static int
-run_inference_each (npudev_h dev, const char *base_path, const char *target)
-{
- generic_buffer model;
- input_buffers input;
- output_buffers output;
-
- char model_path[MAX_FILE_LEN];
- char input_path[MAX_TENSORS][MAX_FILE_LEN];
- off_t input_size;
-
- npuConstraint constraint;
- npubin_meta *meta;
- uint32_t model_id;
- uint32_t idx;
- int err = 0;
-
- /** 1: setup model (not dmabuf) */
- memset (model_path, '\x00', MAX_FILE_LEN);
- snprintf (model_path, MAX_FILE_LEN, "%s/%s/%s",
- base_path, target, NPU_MODEL_NAME);
-
- meta = getNPUmodel_metadata (model_path, false);
- if (meta == NULL) {
- fprintf (stderr, "Fail to get the metadata of %s\n", model_path);
- return -EINVAL;
- }
-
- model.size = get_file_size (model_path);
- model.filepath = model_path;
- model.type = BUFFER_FILE;
-
- /** 2: setup input buffers */
- if (NPUBIN_VERSION (meta->magiccode) != 3) {
- fprintf (stderr, "Support only npubinfmt v3\n");
- err = -EINVAL;
- goto out_free_meta;
- }
-
- for (idx = 0; idx < meta->input_seg_num; idx++) {
- memset (input_path[idx], '\x00', MAX_FILE_LEN);
- snprintf (input_path[idx], MAX_FILE_LEN, "%s/%s/input_fmap_%d.bin",
- base_path, target, idx);
-
- input_size = get_file_size (input_path[idx]);
- if (input_size <= 0) {
- fprintf (stderr, "Wrong metadata; need %d input tensors\n", meta->input_seg_num);
- err = -EINVAL;
- goto out_free_meta;
- }
-
- input.bufs[idx].size = input_size;
- input.bufs[idx].type = BUFFER_FILE;
- input.bufs[idx].filepath = input_path[idx];
- }
-
- input.num_buffers = meta->input_seg_num;
-
- /** 3: allocate input buffers (it's not mandatory to use this API) */
- if ((err = allocNPU_inputBuffers (dev, &input)) != 0) {
- fprintf (stderr, "Fail to allocate NPU input buffer (errno %d)\n", err);
- goto out_free_meta;
- }
-
- /** 4: register the model to NPU Engine */
- if ((err = registerNPUmodel (dev, &model, &model_id)) != 0) {
- fprintf (stderr, "Fail to registerNPU model (errno %d)\n", err);
- goto out_clean;
- }
-
- /** 4-1: provide additional information to NPU Engine */
- {
- tensors_data_info info_in;
- tensors_data_info info_out;
-
- /* No data manipulation & quantization in this test */
-
- info_in.num_info = meta->input_seg_num;
- for (idx = 0; idx < info_in.num_info; idx++) {
- info_in.info[idx].layout = DATA_LAYOUT_TRIV2;
- info_in.info[idx].type = DATA_TYPE_QASYMM8;
- }
-
- info_out.num_info = meta->output_seg_num;
- for (idx = 0; idx < info_out.num_info; idx++) {
- info_out.info[idx].layout = DATA_LAYOUT_TRIV2;
- info_out.info[idx].type = DATA_TYPE_QASYMM8;
- }
-
- if ((err = setNPU_dataInfo (dev, model_id, &info_in, &info_out)) != 0) {
- fprintf (stderr, "Failed to set the information for NPU data\n");
- goto out_unregister;
- }
- }
-
- /** 4-2: set constraints */
- constraint.timeout_ms = NPU_TIMEOUT_MS;
- constraint.priority = NPU_PRIORITY_MID;
- constraint.notimode = NPU_INTERRUPT;
- if ((err = setNPU_constraint (dev, model_id, constraint)) != 0)
- goto out_unregister;
-
- /** 5: run NPU inference (sync) */
- if ((err = runNPU_sync (dev, model_id, &input, &output)) != 0)
- goto out_unregister;
-
- /** 6: compare output buffers */
- err = compare_output_buffers (meta, base_path, target, &output);
-
-out_unregister:
- unregisterNPUmodel (dev, model_id);
-out_clean:
- cleanNPU_inputBuffers (dev, &input);
-out_free_meta:
- free (meta);
-
- /** ensure that all memory (allocated by libnpuhost APIs) are successfully freed */
- if (err == 0)
- check_memory_leak (dev);
-
- return err;
-}
-
-/** @brief apptest main */
-int
-main (int argc, char **argv)
-{
- dev_type type = NPUCOND_TRIV2_CONN_SOCIP;
- npudev_h dev;
-
- if (argc < 2) {
- fprintf (stderr, "[APPTEST] %s: SKIPPED\n", argv[0]);
- return 0;
- }
-
- if (argc == 3)
- enable_output_dump = atoi(argv[2]);
-
- if (!(getnumNPUdeviceByType (type) > 0 &&
- getNPUdeviceByType (&dev, type, 0) == 0)) {
- fprintf(stderr, "No available TRIV2 device\n");
- return -1;
- }
-
- return run_apptest (dev, argv, &run_inference_each);
-}
--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2020 Samsung Electronics
+ * Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file tvn_triv2.cc
+ * @date 09 Jul 2020
+ * @brief AppTest to test a single inference for TRIV2 device
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include <ne_test_utils.h>
+
+#include <iomanip>
+
+#include <sys/types.h>
+#include <dirent.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) {}
+
+ /** @brief initilize the device handle */
+ int init (std::string model_dir) {
+ std::string model_path = model_dir + "/model.tvn";
+ npubin_meta * meta = getNPUmodel_metadata (model_path.c_str(), false);
+ if (meta == nullptr) {
+ cerr << "Failed to get the model metadata\n";
+ 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 the device\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 task_id = UtilTRIV2::run (model_id_);
+ if (task_id < 0)
+ return task_id;
+
+ return wait () == 1 ? test_ret_success : test_ret_failure;
+ }
+
+ private:
+ uint32_t model_id_;
+};
+
+/** @brief apptest main */
+int
+main (int argc, char **argv)
+{
+ Tester tester;
+ char * dir_str;
+ int status;
+
+ status = tester.parseArgs (argc, argv, &dir_str, "[models' dir]");
+ if (status == test_ret_skipped || dir_str == nullptr) {
+ cerr << "[APPTEST] " << argv[0] << ": SKIPPED\n";
+ return 0;
+ } else if (status != test_ret_success) {
+ cerr << "[APPTEST] " << argv[0] << ": FAILED (" << status << ")\n";
+ return status;
+ }
+
+ DIR *d = opendir (dir_str);
+ if (!d) {
+ cerr << "Failed to open " << dir_str << "\n";
+ return -errno;
+ }
+
+ uint32_t total_succs, total_fails;
+ struct dirent *dir;
+
+ total_succs = total_fails = 0;
+ while ((dir = readdir (d)) != NULL) {
+ /** a target binary and data are in each sub-directory */
+ if (dir->d_type != DT_DIR)
+ continue;
+ if (dir->d_name[0] == '.')
+ continue;
+
+ cerr << "[APPTEST] " << left << setw (40) << dir->d_name << " Running... ";
+
+ /** initialize triv2 device */
+ string path (dir_str);
+ status = tester.init (path + "/" + dir->d_name);
+ if (status == test_ret_success) {
+ /** run the inference with the device */
+ status = tester.run ();
+ if (status == test_ret_success) {
+ cerr << "PASSED\n";
+ total_succs++;
+ } else {
+ cerr << "FAILED\n";
+ total_fails++;
+ }
+
+ tester.clear ();
+ } else {
+ cerr << "FAILED\n";
+ total_fails++;
+ }
+ }
+
+ cerr << "[APPTEST] " << argv[0] << ": PASSED (" << total_succs << "), "
+ << "FAILED (" << total_fails << ")\n";
+
+ return 0;
+}
if (argc == 3)
enable_output_dump = atoi(argv[2]);
- if (!(getnumNPUdeviceByType (type) > 0 &&
- getNPUdeviceByType (&dev, type, 0) == 0)) {
+ if (getNPUdeviceByTypeAny (&dev, type, default_tops) != 0) {
fprintf(stderr, "No available TRIV2 device\n");
return -1;
}
/** @brief initilize the device handle */
int init (const std::string dir) {
- int num_devices = getnumNPUdeviceByType (TRIV2_TYPE);
- if (num_devices <= 0)
- return -ENODEV;
-
- /** use any available TRIV2 device. (0 <= dev_id < num_devices) */
- int dev_id = num_devices - 1;
-
dir_ = dir;
- return getNPUdeviceByType (&dev_, TRIV2_TYPE, dev_id);
+ return getNPUdeviceByTypeAny (&dev_, TRIV2_TYPE, default_tops);
}
/** @brief run the inference (with dummy data) */
int init (const npubin_meta *meta) {
/** let's emulate an external dmabuf using TRIV2 */
- int status = getNPUdeviceByType (&dev_, TRIV2_TYPE, 0);
+ int status = getNPUdeviceByTypeAny (&dev_, TRIV2_TYPE, default_tops);
if (status != 0)
return status;
/** @brief destructor of UtilTrinity */
UtilTrinity::~UtilTrinity () {
+ clear ();
+}
+
+/** @brief device instance cleanup */
+void UtilTrinity::clear () {
if (dev_ != nullptr) {
unregisterNPUmodel_all (dev_);
putNPUdevice (dev_);
+ dev_ = nullptr;
}
models_.clear ();
}
/** @brief initialize trinity device and get the device handle */
-int UtilTrinity::init ()
+int UtilTrinity::init (uint32_t tops)
{
- int num_devices = getnumNPUdeviceByType (type_);
- if (num_devices <= 0)
- return -ENODEV;
-
- /** use any available device. (0 <= dev_id < num_devices) */
- int dev_id = num_devices - 1;
- return getNPUdeviceByType (&dev_, type_, dev_id);
+ return getNPUdeviceByTypeAny (&dev_, type_, tops);
}
/** @brief print program usage */
void setMute ();
void setNotiMode (const std::string mode);
- int init ();
+ 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 loadModel (std::string dirpath, uint32_t *model_id,
ss_ << "| Trinity System Management Interface |\n";
ss_ << "| Copyright (C) Samsung Electronics Ltd. |\n";
ss_ << "| |\n";
- ss_ << "| TRINITY-SMI: " << smi_ver;
- ss_ << " NPU-ENGINE: " << lib_ver;
- ss_ << " DRIVER-API: ";
+ ss_ << "| TRINITY-SMI: " << left << setw (8) << smi_ver;
+ ss_ << "NPU-ENGINE: " << left << setw (8) << lib_ver;
+ ss_ << "DRIVER-API: ";
ss_ << setw (3);
#ifdef ENABLE_EMUL
ss_ << "SIM";