}
/**
+ * @brief get the stats for the latest apps of the target device
+ * @param[in] dev The NPU device handle
+ * @param[out] stat The instance of app stat
+ * @note The caller has the responsibility to free the resources.
+ * This API is not working on the emulated envionment.
+ */
+int getNPU_statApps (npudev_h dev, npu_stat_apps *stat)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+#ifdef ENABLE_EMUL
+ logwarn (TAG, "we don't support statistics for the emulated envionment");
+ if (stat) {
+ stat->num = 0;
+ stat->stat = nullptr;
+ }
+ return 0;
+#else
+ return host_handler->getStatApps (stat);
+#endif
+}
+
+/**
+ * @brief Free the stat instance obtained by getNPU_statApps().
+ * @param[in] stat Stat instance
+ */
+void putNPU_statApps (npu_stat_apps *stat)
+{
+ if (stat) {
+ delete [] stat->stat;
+ stat->num = 0;
+ }
+}
+
+/**
+ * @brief get the stats for the latest tasks of the target app
+ * @param[in] dev The NPU device handle
+ * @param[in] appid The identifier of target app
+ * @param[out] stat The instance of task stat
+ * @note The caller has the responsibility to free the resources.
+ * This API is not working on the emulated envionment.
+ */
+int getNPU_statTasks (npudev_h dev, int appid, npu_stat_tasks *stat)
+{
+ INIT_HOST_HANDLER (host_handler, dev);
+
+#ifdef ENABLE_EMUL
+ logwarn (TAG, "we don't support statistics for the emulated envionment");
+ if (stat) {
+ stat->num = 0;
+ stat->stat = nullptr;
+ }
+ return 0;
+#else
+ return host_handler->getStatTasks (appid, stat);
+#endif
+}
+
+/**
+ * @brief Free the stat instance obtained by getNPU_statTasks().
+ * @param[in] stat Stat instance
+ */
+void putNPU_statTasks (npu_stat_tasks *stat)
+{
+ if (stat) {
+ delete [] stat->stat;
+ stat->num = 0;
+ }
+}
+
+/**
* @brief Send the NN model to NPU.
* @param[in] dev The NPU device handle
* @param[in] modelfile The filepath to the compiled NPU NN model in any buffer_type
}
/**
+ * @brief get the stats for the latest apps of the target device
+ * @param[out] stat The list of app stat
+ * @note The caller has the responsibility to free the resources.
+ * This API is not working on the emulated envionment.
+ */
+int
+HostHandler::getStatApps (npu_stat_apps *stat)
+{
+ const DriverAPI * api = device_->getDriverAPI ();
+ assert (api != nullptr);
+
+ return api->getStatApps (stat);
+}
+
+/**
+ * @brief get the stats for the latest tasks of the target app
+ * @param[in] appid The identifier of target app
+ * @param[out] stat The list of task stat
+ * @note The caller has the responsibility to free the resources.
+ * This API is not working on the emulated envionment.
+ */
+int
+HostHandler::getStatTasks (int appid, npu_stat_tasks *stat)
+{
+ const DriverAPI * api = device_->getDriverAPI ();
+ assert (api != nullptr);
+
+ return api->getStatTasks (appid, stat);
+}
+
+/**
* @brief Get the driver API level of opened NPU device
* @param[out] level driver API level
* @return 0 if no error, otherwise a negative errno
TrinityVision2API::numRequests () const
{
if (this->initialized()) {
- uint32_t num_requests;
+ struct trinity_ioctl_stat_apps stat;
int ret;
- ret = ioctl (this->getDeviceFD (), TRINITY_IOCTL_NUM_REQUESTS, &num_requests);
- if (ret == 0)
+ ret = ioctl (this->getDeviceFD (), TRINITY_IOCTL_STAT_APPS, &stat);
+ if (ret == 0) {
+ uint32_t num_requests = 0;
+
+ for (uint32_t i = 0; i < stat.num_apps; i++)
+ num_requests += stat.stat[i].num_active_tasks;
+
return num_requests;
+ }
}
return 0;
int
TrinityVision2API::getMemoryStatus (size_t *alloc_total, size_t *free_total) const
{
- struct trinity_memory_stat stat;
+ struct trinity_ioctl_stat_app stat;
int ret;
if (!initialized())
if (alloc_total == nullptr || free_total == nullptr)
return -EINVAL;
- ret = ioctl (this->getDeviceFD (), TRINITY_IOCTL_MEMORY_STATUS, &stat);
+ ret = ioctl (this->getDeviceFD (), TRINITY_IOCTL_STAT_CURRENT_APP, &stat);
if (ret < 0)
return -errno;
return ret;
}
+
+int
+TrinityVision2API::getStatApps (npu_stat_apps *stat) const
+{
+ struct trinity_ioctl_stat_apps stat_apps;
+ int ret;
+
+ if (!this->initialized())
+ return -EPERM;
+
+ if (stat == nullptr)
+ return -EINVAL;
+
+ stat->num = 0;
+ stat->stat = nullptr;
+
+ ret = ioctl (this->getDeviceFD (), TRINITY_IOCTL_STAT_APPS, &stat_apps);
+ if (ret != 0)
+ return -errno;
+
+ stat->num = stat_apps.num_apps;
+ if (stat->num == 0)
+ return 0;
+
+ stat->stat = new npu_stat_app[stat->num];
+
+ for (uint32_t i = 0; i < stat->num; i++) {
+ struct trinity_ioctl_stat_app *stat_app = &(stat_apps.stat[i]);
+
+ strncpy (stat->stat[i].name, stat_app->name, TRINITY_APP_NAME_MAX - 1);
+
+ stat->stat[i].appid = stat_app->appid;
+ stat->stat[i].status = static_cast<npu_app_status>(stat_app->status);
+
+ stat->stat[i].num_total_tasks = stat_app->num_total_tasks;
+ stat->stat[i].num_active_tasks = stat_app->num_active_tasks;
+
+ stat->stat[i].total_alloc_mem = stat_app->total_alloc_mem;
+ stat->stat[i].total_freed_mem = stat_app->total_freed_mem;
+ }
+
+ return 0;
+}
+
+int
+TrinityVision2API::getStatTasks (int appid, npu_stat_tasks *stat) const
+{
+ struct trinity_ioctl_stat_tasks stat_tasks;
+ int ret;
+
+ if (!this->initialized())
+ return -EPERM;
+
+ if (stat == nullptr)
+ return -EINVAL;
+
+ stat->num = 0;
+ stat->stat = nullptr;
+
+ stat_tasks.appid = appid;
+ ret = ioctl (this->getDeviceFD (), TRINITY_IOCTL_STAT_TASKS, &stat_tasks);
+ if (ret != 0)
+ return -errno;
+
+ stat->num = stat_tasks.num_tasks;
+ if (stat->num == 0)
+ return 0;
+
+ stat->stat = new npu_stat_task[stat->num];
+
+ for (uint32_t i = 0; i < stat->num; i++) {
+ struct trinity_ioctl_stat_task *stat_task = &(stat_tasks.stat[i]);
+
+ stat->stat[i].taskid = stat_task->taskid;
+ stat->stat[i].modelid = stat_task->modelid;
+
+ stat->stat[i].priority = static_cast<npu_priority>(stat_task->priority);
+ stat->stat[i].status = static_cast<npu_task_status>(stat_task->status);
+
+ stat->stat[i].sched_time = stat_task->sched_time;
+ stat->stat[i].infer_time = stat_task->infer_time;
+ }
+
+ return 0;
+}
}
~TrinitySMI () {}
- uint32_t get_api_level ();
+ bool check_arguments (int argc, char ** argv);
void append_version ();
- void append_help ();
- void append_devices ();
- void append_processes ();
+ void append_stats ();
void dump ();
+ void set_device (string node) { node_ = node; }
+ void set_appid (string appid) { appid_ = appid; }
+
private:
+ uint32_t get_api_level ();
+ bool parse_device_node (dev_type & type, int & dev_id);
+ bool parse_app_id (int & app_id);
+ string to_hex_string (uint64_t val);
+
+ void append_help ();
+ void append_devices ();
+ void append_apps ();
+ void append_tasks ();
+
string name_;
stringstream ss_;
+
+ string appid_;
+ string node_;
};
/** @brief get driver api level from any device */
return level;
}
+/** @brief parse the given device node */
+bool
+TrinitySMI::parse_device_node (dev_type & type, int & dev_id)
+{
+ const char * last = strrchr (node_.c_str(), '-');
+
+ dev_id = -1;
+ if (last != NULL && *(last + 1) != '\x00') {
+ char *endptr;
+ errno = 0;
+ dev_id = strtol (last + 1, &endptr, 10);
+ if (errno != 0 || last + 1 == endptr)
+ dev_id = -1;
+ }
+
+ type = NPUCOND_CONN_UNKNOWN;
+ if (node_.find ("triv2-") != string::npos)
+ type = NPUCOND_TRIV2_CONN_SOCIP;
+ else if (node_.find ("triv-") != string::npos)
+ type = NPUCOND_TRIV_CONN_SOCIP;
+ else if (node_.find ("tria-") != string::npos)
+ type = NPUCOND_TRIA_CONN_SOCIP;
+
+ if (dev_id < 0 || type == NPUCOND_CONN_UNKNOWN) {
+ ss_ << "| Invalid device node provided: " << left << setw(29) << node_ << "|\n";
+ ss_ << "+------------------------------------------------------------+\n";
+
+ return false;
+ }
+
+ return true;
+}
+
+/** @brief parse the given app id */
+bool
+TrinitySMI::parse_app_id (int & app_id)
+{
+ const char *nptr = appid_.c_str();
+ char *endptr;
+
+ errno = 0;
+ app_id = strtol (nptr, &endptr, 10);
+
+ if (errno != 0 || nptr == endptr) {
+ ss_ << "| Invalid app id provided: " << left << setw(34) << appid_ << "|\n";
+ ss_ << "+------------------------------------------------------------+\n";
+
+ return false;
+ }
+ return true;
+}
+
+/** @brief convert a value to the hex string */
+string
+TrinitySMI::to_hex_string (uint64_t val)
+{
+ stringstream ss;
+
+ ss << "0x";
+ ss << hex << val;
+
+ return ss.str();
+}
+
/** @brief show the version of npu-engine and driver */
void
TrinitySMI::append_version ()
uint32_t api_level = get_api_level ();
ss_ << std::ctime (&now_time);
- ss_ << "+--------------------------------------------------------+\n";
- ss_ << "| TRINITY-SMI: " << smi_ver;
- ss_ << " NPU-ENGINE: " << lib_ver;
- ss_ << " DRIVER-API: ";
+ ss_ << "+------------------------------------------------------------+\n";
+ 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_ << setw (3);
#ifdef ENABLE_EMUL
ss_ << "SIM";
#else
ss_ << (api_level == 0 ? "INV" : to_string (api_level));
#endif
- ss_ << " |\n";
- ss_ << "+--------------------------------------------------------+\n";
+ ss_ << " |\n";
+ ss_ << "+------------------------------------------------------------+\n";
+}
+
+/** @brief main routine to append stats */
+void
+TrinitySMI::append_stats ()
+{
+ if (!node_.empty ()) {
+ if (!appid_.empty ()) {
+ append_tasks ();
+ } else {
+ append_apps ();
+ }
+ } else {
+ append_devices ();
+ }
}
/** @brief show the list of trinity devices */
NPUCOND_TRIA_CONN_SOCIP
};
- ss_ << "+--------------------------------------------------------+\n";
- ss_ << "| CLASS | DEVICE NODE | TOPS | STATUS | # REQUESTS |\n";
- ss_ << "|========================================================|\n";
+ ss_ << "\n";
+ ss_ << "+------------------------------------------------------------+\n";
+ ss_ << "| CLASS | DEVICE NODE | TOPS | STATUS | # REQUESTS |\n";
+ ss_ << "|============================================================|\n";
uint32_t count = 0;
for (auto type : types) {
putNPUdevice (dev);
#endif
- ss_ << "| " << right << setw (5) << cls << " ";
- ss_ << "| " << right << setw (13) << node_str << " ";
+ ss_ << "| " << right << setw (7) << cls << " ";
+ ss_ << "| " << right << setw (15) << node_str << " ";
ss_ << "| " << right << setw (4) << tops_str << " ";
ss_ << "| " << right << setw (8) << status_str << " ";
ss_ << "| " << right << setw (12) << num_str << " |\n";
}
}
if (count == 0)
- ss_ << "| " << left << setw (55) << "No available device detected" << "|\n";
- ss_ << "+--------------------------------------------------------+\n";
+ ss_ << "| " << left << setw (59) << "No available device detected" << "|\n";
+ ss_ << "+------------------------------------------------------------+\n";
+}
+
+/** @brief show the list of executed apps */
+void
+TrinitySMI::append_apps ()
+{
+ ss_ << "\n";
+ ss_ << "+------------------------------------------------------------+\n";
+ ss_ << "| APP ID | APP NAME | STATUS | MEM (KiB) | # RUNS |\n";
+ ss_ << "|============================================================|\n";
+
+#ifndef ENABLE_EMUL
+ dev_type type;
+ int dev_id;
+
+ if (!parse_device_node (type, dev_id))
+ return;
+
+ uint32_t count = 0;
+ npudev_h dev;
+ npu_stat_apps stat_apps;
+
+ if (getNPUdeviceByType (&dev, type, dev_id) != 0)
+ goto out;
+
+ if (getNPU_statApps (dev, &stat_apps) != 0)
+ goto out_free;
+
+ for (uint32_t i = 0; i < stat_apps.num; i++) {
+ npu_stat_app *stat = &(stat_apps.stat[i]);
+ string status_str;
+
+ if (stat->status == NPU_APP_ERROR)
+ status_str = string ("error");
+ else if (stat->status == NPU_APP_PENDING)
+ status_str = string ("pending");
+ else if (stat->status == NPU_APP_STARTED)
+ status_str = string ("started");
+ else if (stat->status == NPU_APP_TERMINATED)
+ status_str = string ("terminated");
+ else
+ status_str = string ("unknown");
+
+ ss_ << "| " << right << setw(6) << stat->appid << " ";
+ ss_ << "| " << right << setw(15) << stat->name << " ";
+ ss_ << "| " << right << setw(10) << status_str << " ";
+ ss_ << "| " << right << setw(9) << fixed << setprecision(2);
+ ss_ << (((double) stat->total_alloc_mem) / 1024.0) << " ";
+ ss_ << "| " << right << setw(6) << stat->num_total_tasks << " |\n";
+ count++;
+ }
+
+ putNPU_statApps (&stat_apps);
+
+out_free:
+ putNPUdevice (dev);
+out:
+ if (count == 0)
+ ss_ << "| " << left << setw (59) << "No executed applications found" << "|\n";
+#else
+ ss_ << "| " << left << setw (59) << "Not supported envionment" << "|\n";
+#endif
+
+ ss_ << "+------------------------------------------------------------+\n";
}
-/** @brief show the list of running processes */
+/** @brief show the list of submitted tasks */
void
-TrinitySMI::append_processes ()
+TrinitySMI::append_tasks ()
{
- /** TODO */
- ss_ << "+--------------------------------------------------------+\n";
- ss_ << "| " << left << setw (55) << "No running processes found" << "|\n";
- ss_ << "+--------------------------------------------------------+\n";
+ ss_ << "\n";
+ ss_ << "+------------------------------------------------------------+\n";
+ ss_ << "| TASK ID | MODEL ID | PRIO | STATUS | SCHED | INFER |\n";
+ ss_ << "|============================================================|\n";
+
+#ifndef ENABLE_EMUL
+ dev_type type;
+ int dev_id, app_id;
+
+ if (!parse_device_node (type, dev_id))
+ return;
+
+ if (!parse_app_id (app_id))
+ return;
+
+ uint32_t count = 0;
+ npudev_h dev;
+ npu_stat_tasks stat_tasks;
+
+ if (getNPUdeviceByType (&dev, type, dev_id) != 0)
+ goto out;
+
+ if (getNPU_statTasks (dev, app_id, &stat_tasks) != 0)
+ goto out_free;
+
+ for (uint32_t i = 0; i < stat_tasks.num; i++) {
+ npu_stat_task *stat = &(stat_tasks.stat[i]);
+ string priority_str;
+ string status_str;
+
+ if (stat->priority == NPU_PRIORITY_HIGH)
+ priority_str = string ("high");
+ else if (stat->priority == NPU_PRIORITY_MID)
+ priority_str = string ("mid");
+ else if (stat->priority == NPU_PRIORITY_LOW)
+ priority_str = string ("low");
+ else
+ priority_str = string ("unknown");
+
+ if (stat->status == NPU_TASK_ERROR)
+ status_str = string ("error");
+ else if (stat->status == NPU_TASK_PENDING)
+ status_str = string ("pending");
+ else if (stat->status == NPU_TASK_RUNNING)
+ status_str = string ("running");
+ else if (stat->status == NPU_TASK_FINISHED)
+ status_str = string ("finished");
+ else
+ status_str = string ("unknown");
+
+ ss_ << "| " << right << setw(7) << stat->taskid << " ";
+ ss_ << "| " << right << setw(10) << to_hex_string (stat->modelid) << " ";
+ ss_ << "| " << right << setw(4) << priority_str << " ";
+ ss_ << "| " << right << setw(8) << status_str << " ";
+ ss_ << "| " << right << setw(7) << to_string (stat->sched_time) + "ms" << " ";
+ ss_ << "| " << right << setw(7) << to_string (stat->infer_time) + "ms" << " |\n";
+ count++;
+ }
+
+ putNPU_statTasks (&stat_tasks);
+
+out_free:
+ putNPUdevice (dev);
+out:
+ if (count == 0)
+ ss_ << "| " << left << setw (59) << "No submitted tasks found" << "|\n";
+
+#else
+ ss_ << "| " << left << setw (59) << "Not supported envionment" << "|\n";
+#endif
+
+ ss_ << "+------------------------------------------------------------+\n";
}
/** @brief show the usage and help messages */
{
ss_ << "\nUsage: " << name_ << " [options]\n";
ss_ << "Options:\n";
- ss_ << " -d \t\t Show list of trinity devices\n";
- ss_ << " -p \t\t Show list of running processes\n";
- ss_ << " -h \t\t Show help messages\n";
+ ss_ << " -h \t\tShow help messages\n";
+ ss_ << " -d [dev node] Specify a device node that you're interested in\n";
+ ss_ << "\t\t(e.g., -d triv2-0)\n";
+ ss_ << " -a [app id] \tSpecify a app id that you're interested in\n";
+ ss_ << "\t\t(e.g., -d triv2-0 -a 125)\n";
+}
+
+/** @brief check the given arguments */
+bool
+TrinitySMI::check_arguments (int argc, char ** argv)
+{
+ int c;
+
+ optind = 0;
+ opterr = 0;
+ while ((c = getopt (argc, argv, "hd:a:")) != -1) {
+ switch (c) {
+ case 'd':
+ set_device (optarg);
+ break;
+ case 'a':
+ set_appid (optarg);
+ break;
+ case '?':
+ if (optopt == 'd')
+ ss_ << "\nOption '-d' requires an extra argument\n";
+ else if (optopt == 'a')
+ ss_ << "\nOption '-a' requires an extra argument\n";
+ else
+ ss_ << "\nUnknown flag detected: " << (char) optopt << "\n";
+ // no-break
+ case 'h':
+ append_help ();
+ return false;
+ }
+ }
+
+ if (!appid_.empty () && node_.empty ()) {
+ ss_ << "\nOption '-a' requires Option '-d' as well, to specify a device node\n";
+ append_help ();
+ return false;
+ }
+
+ return true;
}
/** @brief show the appended string to screen */
TrinitySMI smi (argv[0]);
smi.append_version ();
-
- if (argc > 1) {
- int c;
-
- optind = 0;
- opterr = 0;
- while ((c = getopt (argc, argv, "dph")) != -1) {
- switch (c) {
- case 'd':
- smi.append_devices ();
- break;
- case 'p':
- smi.append_processes ();
- break;
- case 'h':
- smi.append_help ();
- break;
- }
- }
- } else {
- smi.append_help ();
- }
-
+ if (smi.check_arguments (argc, argv))
+ smi.append_stats ();
smi.dump ();
+
return 0;
}