diff --git a/demo/lenet_pack.c b/demo/lenet_pack.c new file mode 100644 index 0000000..6e888c9 --- /dev/null +++ b/demo/lenet_pack.c @@ -0,0 +1,78 @@ +#include +#include + +#include "catcoon.h" + +#define INPUT_W 28 +#define INPUT_H 28 + +const char *parameters_files[]={ + "conv1_w.bin", + "conv1_b.bin", + "conv2_w.bin", + "conv2_b.bin", + "fc1_w.bin", + "fc1_b.bin", + "fc2_w.bin", + "fc2_b.bin", +}; +const char *parameters_path = "/home/evi/catcoon-pytorch-model/lenet/dump"; +const char *parameters_pack = "lenet_parameters.bin"; + +int main(int argc, const char *argv[]) +{ + cc_int32 i = 0; + char filepath[256]; + cc_int32 shape_conv1_w[] = {5, 5, 1, 32, 0}; + cc_int32 shape_conv1_b[] = {32, 0}; + cc_int32 shape_conv2_w[] = {5, 5, 32, 64, 0}; + cc_int32 shape_conv2_b[] = {64, 0}; + cc_int32 shape_fc1_w[] = {1, 1, 3136, 128, 0}; + cc_int32 shape_fc1_b[] = {128, 0}; + cc_int32 shape_fc2_w[] = {1, 1, 128, 10, 0}; + cc_int32 shape_fc2_b[] = {10, 0}; + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_conv1_w, CC_FLOAT32, "conv1_w"); + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_conv1_b, CC_FLOAT32, "conv1_b"); + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_conv2_w, CC_FLOAT32, "conv2_w"); + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_conv2_b, CC_FLOAT32, "conv2_b"); + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_fc1_w, CC_FLOAT32, "fc1_w"); + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_fc1_b, CC_FLOAT32, "fc1_b"); + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_fc2_w, CC_FLOAT32, "fc2_w"); + + sprintf(filepath, "%s/%s", + parameters_path, parameters_files[i++]); + cc_load_bin(filepath, + shape_fc2_b, CC_FLOAT32, "fc2_b"); + cc_tsrmgr_list(); + cc_tsrmgr_export(parameters_pack); + cc_clear(); + return 0; +} diff --git a/demo/lenet_unpack.c b/demo/lenet_unpack.c new file mode 100644 index 0000000..6e78dcf --- /dev/null +++ b/demo/lenet_unpack.c @@ -0,0 +1,85 @@ +#include +#include + +#include "catcoon.h" + +#define INPUT_W 28 +#define INPUT_H 28 + +const char *parameters_path = "./lenet_parameters.bin"; + +int main(int argc, const char *argv[]) +{ + cc_int32 i, j; + cc_float32 v; + /* Image */ + utim_image_t *img, *img_read; + /* Layers */ + cc_tensor_t *input,*l1, *l1_pool, *l2, *l2_pool, *l2_flat, *l3, *l4; + /* Parameters */ + cc_tensor_t *conv1_w, *conv1_b, + *conv2_w, *conv2_b, *fc1_w, *fc1_b, *fc2_w, *fc2_b; + cc_int32 shape_flat[] = {-1, 1, 1, 0}; + + if (argc < 2) { + fprintf(stderr, "usage: lenet [filename]\n"); + exit(255); + } + + /* load parameters */ + cc_tsrmgr_import(parameters_path); + conv1_w = cc_tsrmgr_get("conv1_w"); + conv1_b = cc_tsrmgr_get("conv1_b"); + conv2_w = cc_tsrmgr_get("conv2_w"); + conv2_b = cc_tsrmgr_get("conv2_b"); + fc1_w = cc_tsrmgr_get("fc1_w"); + fc1_b = cc_tsrmgr_get("fc1_b"); + fc2_w = cc_tsrmgr_get("fc2_w"); + fc2_b = cc_tsrmgr_get("fc2_b"); + + img_read = utim_read(argv[1]); + utim_img2gray(img_read); + img = utim_resize(img_read, INPUT_H, INPUT_W, 0); + input = cc_image2tensor(img, "input"); + utim_free_image(img); + utim_free_image(img_read); + input = cc_cast_tensor(input, CC_FLOAT32, "input"); + v = 255.; + input = cc_tensor_by_scalar(input, '/', &v, "input"); + + l1 = cc_conv2d(input, conv1_w, conv1_b, 1, 2, 0, "l1_conv"); + + l1 = cc_relu(l1, NULL); + + l1_pool = cc_max_pool2d(l1, 2, "l1_pool"); + + l2 = cc_conv2d(l1_pool, conv2_w, conv2_b, 1, 2, 0, "l2_conv"); + + l2 = cc_relu(l2, NULL); + + l2_pool = cc_max_pool2d(l2, 2, "l2_pool"); + + /* l2_flat = cc_fmap2d_flat(l2_pool, "l2_flat"); */ + l2_flat = cc_tensor_reshape(l2_pool, shape_flat); + + l3 = cc_fully_connected(l2_flat, fc1_w, fc1_b, "fc1"); + + l3 = cc_relu(l3, NULL); + + l4 = cc_fully_connected(l3, fc2_w, fc2_b, "fc2"); + + l4 = cc_softmax(l4, NULL); + + v = 0.; + for (i = 0, j = 0; i < 10; ++i) { + if (*((cc_float32*)l4->data + i) > v) { + v = *((cc_float32*)l4->data + i); + j = i; + } + printf("[%d]: %f\n", i, *((cc_float32*)l4->data + i)); + } + printf("Result of \"%s\": [%d]\n", argv[1], j); + cc_tsrmgr_list(); + cc_clear(); + return 0; +} diff --git a/makefile b/makefile index 485a3dd..9f417ee 100644 --- a/makefile +++ b/makefile @@ -3,7 +3,7 @@ cc = gcc # Debug flag, cc_assert DFLAG += -DENABLE_CC_ASSERT # AddressSanitizer for gcc/clang -DFLAG += # -g -fsanitize=address -fno-omit-frame-pointer +DFLAG += -g -fsanitize=address -fno-omit-frame-pointer CFLAG += # -std=c89 CFLAG += -Wall # -Wpedantic @@ -37,7 +37,7 @@ ALL_O = catcoon.o cc_tensor.o cc_dtype.o cc_tsrmgr.o cc_fmap2d.o cc_pool2d.o \ cc_conv2d.o cc_normfn.o cc_image.o util_rbt.o util_list.o util_log.o \ util_image.o global_fn_cfg.o -APP_NAMES = simple lenet +APP_NAMES = simple lenet lenet_pack lenet_unpack ifeq ($(OS),Windows_NT) RM = del diff --git a/src/cc_tsrmgr.c b/src/cc_tsrmgr.c index 43466c0..4a9585f 100644 --- a/src/cc_tsrmgr.c +++ b/src/cc_tsrmgr.c @@ -221,11 +221,15 @@ void cc_tsrmgr_list(void) list_t *cc_tsrmgr_pack() { list_t *pack; - cc_uint8 *dptr; - cc_int32 len, off; cc_tensor_t *csr; - cc_int32 i, idc = 0; - rbt_iterator *it = new_rbt_iterator(global_tsrmgr_table); + cc_uint8 *dptr; + cc_int32 len, off, i, idc = 0; + rbt_iterator *it; + if (!global_tsrmgr_table) { + utlog_format(UTLOG_WARN, "cc_tsrmgr: not initialized\n"); + return NULL; + } + cc_assert_ptr(it = new_rbt_iterator(global_tsrmgr_table)); cc_assert_ptr(pack = list_new_dynamic(global_counter)); while (rbt_iterator_has_next(it)) { csr = (cc_tensor_t*) @@ -254,6 +258,8 @@ void cc_tsrmgr_unpack(list_t *tls) list_t *container; cc_uint8 *dptr, *rptr; cc_int32 i, j, off, len; + if (!cc_tsrmgr_status()) + cc_tsrmgr_init(); for (i = 0; i < tls->counter; ++i) { cc_assert_ptr( container = list_new_dynamic(CC_TENSOR_ITEMS)); @@ -285,3 +291,19 @@ void cc_tsrmgr_unpack(list_t *tls) cc_tsrmgr_reg(t); } } + +void cc_tsrmgr_export(const char *filename) +{ + list_t *pack; + cc_assert_ptr(pack = cc_tsrmgr_pack()); + cc_assert_zero(list_export(pack, filename, NULL)); + list_del(pack); +} + +void cc_tsrmgr_import(const char *filename) +{ + list_t *pack; + cc_assert_ptr(pack = list_import(filename)); + cc_tsrmgr_unpack(pack); + list_del(pack); +} \ No newline at end of file diff --git a/src/cc_tsrmgr.h b/src/cc_tsrmgr.h index 25262e8..6293cdc 100644 --- a/src/cc_tsrmgr.h +++ b/src/cc_tsrmgr.h @@ -12,6 +12,7 @@ void cc_tsrmgr_clear(void); void cc_tsrmgr_reg(cc_tensor_t *tensor); void cc_tsrmgr_del(const char *name); +void cc_tsrmgr_update(cc_tensor_t *tensor); void cc_tsrmgr_replace(cc_tensor_t *tensor); int cc_tsrmgr_status(void); @@ -27,6 +28,9 @@ void cc_tsrmgr_list(void); list_t *cc_tsrmgr_pack(); void cc_tsrmgr_unpack(list_t *tls); +void cc_tsrmgr_export(const char *filename); +void cc_tsrmgr_import(const char *filename); + /* AUTO_TSRMGR */ #define cc_tsrmgr_auto_reg(tensor) \ if (!cc_tsrmgr_status()) \