test_decompose_api.c
This is an example code of DNN decomposing and squashing.
Usage
$ test_decompose_api IDNN ODNN LAYER#0 [LAYER#k]
Arguments
- IDNN: The input DNN model file (*.dnn) to be decomposed and squashed.
- ODNN: The output DNN file (*.dnn).
- LAYER#k: The layer names of the split position.
The input DNN is decomposed at the split position specified by LAYER#k. If LAYER#0 and LAYER#1 are given, the net is decomposed to three subnets, i.e. source - LAYER#0, LAYER#0 - LAYER#1, and LAYER#1 - sink.
Then the main net (the most computationally expensive subnet is regarded as main net) is squashed to pseudo single layer of type complex.
The main purpose of decomposing and squashing is to make the complex layer be calculated by different inference engine.
Example Result
$ ls
mobilenet.dnn test_decompose_api
$ test_decompose_api mobilenet.dnn mobilenet_decomposed.dnn conv_pw_13 reshape_1
add interval input_1 - conv_pw_13s
add interval conv_pw_13 - reshape_1
add interval reshape_1 - sink_0
write to mobilenet_decomposed.dnn
$ ls
mobilenet.dnn mobilenet_decomposed.dnn test_decompose_api
Sample Code
#include "morapi_softneuro.h"
#include <stdio.h>
#include <stdlib.h>
/* Command usage. */
void
usage(void)
{
printf("test_decompose_api IDNN ODNN LAYER#0 [LAYER#k]\n"
"\n"
"decompose, squash a dnn.\n"
"\n"
"positional arguments:\n"
" IDNN the input dnn.\n"
" ODN the output dnn.\n"
" LAYER#k the split layers (One or more need to be specified).\n");
}
int
main(int argc, char **argv)
{
morapi_Result ret = MORAPI_OK;
morapi_Env *env = NULL;
morapi_Dnn *dnn = NULL;
morapi_DnnNet *net = NULL;
morapi_DnnNetPartition *part = NULL;
morapi_Bool use_squash = MORAPI_TRUE;
if (argc <= 3) {
usage();
return 0;
}
/* create env. */
env = morapi_create_Env(NULL, 0);
ret |= morapi_Env_setLogFunc(env, (morapi_LogFunc)&fprintf, stderr);
ret |= morapi_Env_setMsgFunc(env, (morapi_LogFunc)&fprintf, (morapi_FlushFunc)&fflush, stdout);
/* create objects. */
dnn = morapi_create_Dnn(env);
/* load dnn. */
if (MORAPI_OK != (ret |= morapi_Dnn_load(dnn, argv[1], NULL, 0, MORAPI_TRUE))) {
printf("load fail\n");
goto EXIT;
}
net = morapi_Dnn_findMainNet(dnn);
{
int l, l_num = (argc - 3) + 2;
char **layers = malloc(sizeof(char*) * l_num);
layers[0] = morapi_DnnLayer_getName(morapi_DnnNet_getInputLayer(net, 0));
for(l = 1; l < (l_num - 1); l += 1){
layers[l] = argv[3+l-1];
}
layers[l_num-1] = morapi_DnnLayer_getName(morapi_DnnNet_getOutputLayer(net, 0));
part = morapi_create_DnnNetPartition(env);
for(l = 0; l < (l_num-1); l += 1){
morapi_DnnLayer *layer = morapi_DnnNet_findLayer(net, layers[l]);
morapi_DnnLayer *next_layer = morapi_DnnNet_findLayer(net, layers[l+1]);
if(NULL == layer || NULL == next_layer){
printf("layer not found\n");
free(layers);
goto EXIT;
}
ret |= morapi_DnnNetPartition_addInterval(part, layers[l], layers[l+1]);
printf("add interval %s - %s\n", layers[l], layers[l+1]);
}
free(layers);
}
if (MORAPI_OK != (ret |= morapi_Dnn_decompose(dnn, net, part))) {
printf("decompose fail\n");
goto EXIT;
}
if (MORAPI_OK != (ret |= morapi_Dnn_removeNet(dnn, net))) {
printf("remove fail\n");
goto EXIT;
}
if (use_squash){
net = morapi_Dnn_findMainNet(dnn);
ret |= morapi_Dnn_squashNet(dnn, net, "squashed");
if(MORAPI_OK != ret){
printf("squash fail\n");
}
}
if (MORAPI_OK != (ret |= morapi_Dnn_save(dnn, argv[2], NULL, 0, MORAPI_FALSE))) {
printf("write fail\n");
goto EXIT;
} else {
printf("write to %s\n", argv[2]);
}
EXIT:
/* destroy objects. */
ret |= morapi_destroy_DnnNetPartition(env, part);
ret |= morapi_destroy_Dnn(env, dnn);
ret |= morapi_destroy_Env(env);
return (int)ret;
}