This patch adds log verbose mode for debugging.
When it's enabled, npu-engine prints log message to stderr
as well as log file, and also dumps the emulated layer data.
Signed-off-by: Dongju Chae <dongju.chae@samsung.com>
- How to setup your own FastModel enviornment (in Ubuntu 16.04 running on your host PC): press [here](https://github.sec.samsung.net/AIP/NPU_bootstrap/blob/master/README.md)
- How to build the NPU Engine library (FastModel or Ubuntu): press [here](/doc/how_to_build.md)
- How to use the NPU Engine library in user apps: press [here](/doc/how_to_use.md)
+- How to debug your apps using the NPU Engine library: press [here](/doc/how_to_debug.md)
- Usage examples using the NPU Engine library: press [here](/doc/usage_examples.md)
- NPU Engine-enabled bootable images for an FPGA board: press [here](https://github.sec.samsung.net/AIP/meta-trinity/blob/linux-xlnx-fpga-v4.19/README.md)
--- /dev/null
+# How to debug your apps using NPU Engine library
+
+First of all, this guide describe how to quickly debug your apps in host PC (i.e., Ubuntu 16.04), before testing on the FastModel Simulator or FPGA boards.
+
+We currently provide two methods to configure the npu-engine library
+- .ini file (`/opt/trinity/etc/npu-engine.ini` in Ubuntu 16.04)
+- enviroment variables
+
+## Log messages
+Basically, the log messages (especially errors) are printed to a log file. The default log file path is `/tmp/npu-engine.log`. Of course, you can configure this using the two methods.
+
+After modifying .ini file
+``` bash
+$ sudo sed -i "s|log_dir=.*|log_dir=/home/test/log_dir|" /opt/trinity/etc/npu-engine.ini
+$ ... [run your apps] ...
+```
+
+After setting the env variable
+``` bash
+$ export NE_LOG_DIR=/home/test/log_dir
+$ ... [run your apps] ...
+```
+
+Note that envionment variables have higher priority and we recommend to use them.
+
+## Layer-level data dump
+To check the intermediate input and output data of each layer, you can set `log_verbose` mode
+
+After modifying .ini file
+``` bash
+$ sudo sed -i "s|log_verbose=.*|log_verbose=true|" /opt/trinity/etc/npu-engine.ini
+$ ... [run your apps] ...
+```
+
+After setting the env variable
+``` bash
+$ export NE_LOG_VERBOSE=true
+$ ... [run your apps] ...
+```
+
+Then, you can find out the dumped input and output data for each layer.
+``` bash
+$ ls [log_dir]/layer_dump
+layer_0 layer_1 layer_2 layer_3 layer_4 ...
+$
+$ ls [log_dir]/layer_dump/layer_1
+input_fmap.bin output_fmap.bin
+$ ...
+```
+
+Note that, in `log_verbose` mode, the log messages are printed to `stderr` as well as a log file.
ne_install_conf.set('RESV_MEM_SIZE', get_option('resv_mem_size'))
ne_install_conf.set('NUM_THREADS', get_option('num_threads'))
ne_install_conf.set('LOG_DIR', get_option('log_dir'))
+ne_install_conf.set('LOG_VERBOSE', get_option('log_verbose'))
# Install .ini
configure_file(input: 'npu-engine.ini.in', output: 'npu-engine.ini',
option('resv_mem_size', type : 'string', value : '0')
option('num_threads', type : 'string', value : '8')
option('log_dir', type : 'string', value : '/tmp/')
+option('log_verbose', type : 'boolean', value : false)
option('enable_npu_emul', type : 'boolean', value : false)
option('enable_data_manip', type : 'boolean', value : false)
option('enable_buffering', type : 'boolean', value : false)
resv_mem_size=@RESV_MEM_SIZE@
num_threads=@NUM_THREADS@
log_dir=@LOG_DIR@
+log_verbose=@LOG_VERBOSE@
#include <NPUemul.h>
#include <npubinfmt.h>
+#include <ne-conf.h>
#define MAX_EMUL_DEVICES (100)
segment_table[i] = static_cast<char *>(elem->getAddr ()) + offset;
}
+ set_triv2_debug (
+ Conf::getInstance().getLogVerbose(),
+ Conf::getInstance().getLogDir());
+
status = run_triv2_emul (addr_model + model->program_offset_addr, model->program_size,
segment_table, num_segs);
delete [] segment_table;
setResvMemSize (std::to_string (default_resv_mem_size).c_str());
setNumThreads (std::to_string (default_num_threads).c_str());
setLogDir (dafault_log_dir);
+ setLogVerbose (default_log_verbose);
}
/**
}
/**
+ * @brief Set the log verbose mode for debugging
+ * @param[in] log_verbose turning on/off verbose mode
+ */
+void
+Conf::setLogVerbose (const char *log_verbose)
+{
+ if (log_verbose && strlen (log_verbose) > 0) {
+ char first_char = log_verbose[0];
+
+ /* let's check the first character only */
+ if (first_char == 'y' || first_char == 'Y' ||
+ first_char == 't' || first_char == 'T' ||
+ first_char == '1')
+ log_verbose_ = true;
+ else
+ log_verbose_ = false;
+ }
+}
+
+/**
* @brief Set the configuration of # threads in thread pool
* @param[in] num_threads config string for a number of threads
*/
const char *log_dir = iniparser_getstring(ini, "main:log_dir", nullptr);
const char *resv_mem_size = iniparser_getstring(ini, "main:resv_mem_size", nullptr);
const char *num_threads = iniparser_getstring (ini, "main:num_threads", nullptr);
+ const char *log_verbose = iniparser_getstring (ini, "main:log_verbose", nullptr);
setLogDir (log_dir);
setResvMemSize (resv_mem_size);
setNumThreads (num_threads);
+ setLogVerbose (log_verbose);
}
/**
const char *log_dir = getenv (ENV_LOG_DIR);
const char *resv_mem_size = getenv (ENV_RESV_MEM_SIZE);
const char *num_threads = getenv (ENV_NUM_THREADS);
+ const char *log_verbose = getenv (ENV_LOG_VERBOSE);
setLogDir (log_dir);
setResvMemSize (resv_mem_size);
setNumThreads (num_threads);
+ setLogVerbose (log_verbose);
}
#define MAX_DIR_LEN 256
#define ENV_LOG_DIR "NE_LOG_DIR"
+#define ENV_LOG_VERBOSE "NE_LOG_VERBOSE"
#define ENV_RESV_MEM_SIZE "NE_RESV_MEM_SIZE"
#define ENV_NUM_THREADS "NE_NUM_THREADS"
static const size_t default_resv_mem_size = 0; /* default mode is the CMA allocation */
static const uint32_t default_num_threads = 8;
static const char dafault_log_dir[] = "/tmp/";
+static const char default_log_verbose[] = "false";
/** @brief Configuration for NPU-Engine components */
class Conf {
size_t getResvMemSize() { return reserved_mem_size_; }
uint32_t getNumThreads() { return num_threads_; }
const char * getLogDir() { return log_dir_; }
+ bool getLogVerbose() { return log_verbose_; }
void reset();
void setResvMemSize (const char *str);
void setNumThreads (const char *str);
void setLogDir (const char *str);
+ void setLogVerbose (const char *str);
size_t reserved_mem_size_;
/**< NE_RESV_MEM_SIZE, [main] resv_mem_size, the size of memory reserved */
/**< NE_NUM_THREADS, [main] num_threads, the number of threads in thread pool */
char log_dir_[MAX_DIR_LEN];
/**< NE_LOG_DIR, [main] log_dir, the path where log files are created */
+ bool log_verbose_;
+ /**< NE_LOG_VERBOSE, [main] log_verbose, verbose mode for debugging */
};
#endif /* __NE_CONF_H__ */
/********************************************************************
* Logging utilities *
********************************************************************/
-#define logfilename "npu-engine.log"
+#define LOG_FILENAME "npu-engine.log"
+#define MAX_LOG_MSG 512
/**
* @brief Log Level String in 5 characters
void
Logger::logwrite (loglevel l, module m, const char *format, ...)
{
- std::unique_lock<std::mutex> lock (m_);
-
- time_t ltime = time (NULL);
- char* time_str;
- va_list args;
-
if (l < LOG_INFO || l >= LOG_END)
return;
if (format == nullptr)
return;
- if (fp_ == NULL) {
- char filename[FILENAME_MAX];
+ std::unique_lock<std::mutex> lock (m_);
- snprintf(filename, FILENAME_MAX, "%s%s",
- Conf::getInstance().getLogDir(), logfilename);
- fp_ = fopen (filename, "a");
- }
+ char log_msg[MAX_LOG_MSG];
+ size_t log_len;
- assert (fp_ != NULL);
+ time_t ltime = time (nullptr);
+ char* time_str;
+ va_list args;
/**
* localtime() and asctime() are not MT-safe. There are alternatives,
* need critical section here.
*/
time_str = asctime (localtime (<ime));
-
time_str[strcspn (time_str, "\n")] = '\x00';
- fprintf (fp_, "[%s][%s][%s] ", loglevelstr[l], modulestr[m], time_str);
+
+ log_len = snprintf (log_msg, MAX_LOG_MSG,
+ "[%s][%s][%s] ", loglevelstr[l], modulestr[m], time_str);
+
va_start (args, format);
- vfprintf (fp_, format, args);
+ log_len += vsnprintf (log_msg + log_len, MAX_LOG_MSG - log_len,
+ format, args);
va_end (args);
+ if (Conf::getInstance().getLogVerbose()) {
+ fprintf (stderr, "%s\n", log_msg);
+ fflush (stderr);
+ }
+
+ if (fp_ == nullptr) {
+ char filename[FILENAME_MAX];
+
+ snprintf(filename, FILENAME_MAX, "%s/%s",
+ Conf::getInstance().getLogDir(), LOG_FILENAME);
+ fp_ = fopen (filename, "a");
+ if (fp_ == nullptr)
+ return;
+ }
+
+ fprintf (fp_, "%s\n", log_msg);
fflush (fp_);
}