diff --git a/.gitignore b/.gitignore index de78410..68b4b70 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ build/ *.tar.gz *.weights .idea/ -*.hdf5 \ No newline at end of file +*.hdf5 +*.pk \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e3d8607..8582bef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,9 @@ cuda_add_library(kernels SHARED ${tkdnn_CUSRC}) #------------------------------------------------------------------------------- # External Libraries #------------------------------------------------------------------------------- +find_package(Eigen3 REQUIRED) +include_directories(${EIGEN3_INCLUDE_DIR}) + find_package(OpenCV REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOPENCV") diff --git a/include/tkDNN/ImuOdom.h b/include/tkDNN/ImuOdom.h new file mode 100644 index 0000000..e3ade02 --- /dev/null +++ b/include/tkDNN/ImuOdom.h @@ -0,0 +1,124 @@ +#include +#include +#include /* srand, rand */ +#include +#include +#include +#include "utils.h" +#include "tkdnn.h" + +namespace tk { namespace dnn { + +/** + * + * @author Francesco Gatti + */ +class ImuOdom { + + public: + tk::dnn::Network *net = nullptr; + + // Network input dim + tk::dnn::dataDim_t dim0; + tk::dnn::dataDim_t dim1; + tk::dnn::dataDim_t dim2; + + // Network output dim + tk::dnn::dataDim_t odim0; + tk::dnn::dataDim_t odim1; + + // input pointers + dnnType *i0_d, *i1_d, *i2_d; + // output pointers + dnnType *o0_d, *o1_d; + + // output eigen CPU + Eigen::MatrixXf deltaP, deltaQ; + + ImuOdom() {} + + virtual ~ImuOdom() {} + + /** + * Method used for inizialize the class + * + * @return Success of the initialization + */ + bool init(std::string layers_path) { + + dim0 = tk::dnn::dataDim_t(1, 4, 1, 100); + dim1 = tk::dnn::dataDim_t(1, 3, 1, 100); + dim2 = tk::dnn::dataDim_t(1, 3, 1, 100); + + checkCuda( cudaMalloc(&i0_d, dim0.tot()*sizeof(dnnType)) ); + checkCuda( cudaMalloc(&i1_d, dim1.tot()*sizeof(dnnType)) ); + checkCuda( cudaMalloc(&i2_d, dim2.tot()*sizeof(dnnType)) ); + + std::string c0_bin = layers_path + "/conv1d_7.bin"; + std::string c1_bin = layers_path + "/conv1d_8.bin"; + std::string c2_bin = layers_path + "/conv1d_9.bin"; + std::string c3_bin = layers_path + "/conv1d_10.bin"; + std::string c4_bin = layers_path + "/conv1d_11.bin"; + std::string c5_bin = layers_path + "/conv1d_12.bin"; + std::string l0_bin = layers_path + "/bidirectional_3.bin"; + std::string l1_bin = layers_path + "/bidirectional_4.bin"; + std::string d0_bin = layers_path + "/dense_3.bin"; + std::string d1_bin = layers_path + "/dense_4.bin"; + + net = new tk::dnn::Network(dim0); + tk::dnn::Input *x0 = new tk::dnn::Input (net, dim0, i0_d); + tk::dnn::Conv2d *x0_0 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c0_bin); + tk::dnn::Conv2d *x0_1 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c1_bin); + tk::dnn::Pooling *x0_2 = new tk::dnn::Pooling(net, 1, 3, 1, 3, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX); + + tk::dnn::Input *x1 = new tk::dnn::Input (net, dim1, i1_d); + tk::dnn::Conv2d *x1_0 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c2_bin); + tk::dnn::Conv2d *x1_1 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c3_bin); + tk::dnn::Pooling *x1_2 = new tk::dnn::Pooling(net, 1, 3, 1, 3, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX); + + tk::dnn::Input *x2 = new tk::dnn::Input (net, dim2, i2_d); + tk::dnn::Conv2d *x2_0 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c4_bin); + tk::dnn::Conv2d *x2_1 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c5_bin); + tk::dnn::Pooling *x2_2 = new tk::dnn::Pooling(net, 1, 3, 1, 3, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX); + + tk::dnn::Layer *concat_l[3] = { x0_2, x1_2, x2_2 }; + tk::dnn::Route *concat = new tk::dnn::Route(net, concat_l, 3); + + tk::dnn::LSTM *lstm0 = new tk::dnn::LSTM(net, 128, true, l0_bin); + tk::dnn::LSTM *lstm1 = new tk::dnn::LSTM(net, 128, false, l1_bin); + + tk::dnn::Dense *d0 = new tk::dnn::Dense(net, 3, d0_bin); + + tk::dnn::Layer *lstm1_l[1] = { lstm1 }; + tk::dnn::Route *lstm1_link = new tk::dnn::Route(net, lstm1_l, 1); + tk::dnn::Dense *d1 = new tk::dnn::Dense(net, 4, d1_bin); + + net->print(); + + // output data + o0_d = d0->dstData; + o1_d = d1->dstData; + odim0 = d0->output_dim; + odim1 = d1->output_dim; + + deltaP.resize(1, odim0.tot()); + deltaQ.resize(1, odim1.tot()); + } + + void update(dnnType *x0, dnnType *x1, dnnType *x2) { + + checkCuda( cudaMemcpy(i0_d, x0, dim0.tot()*sizeof(dnnType), cudaMemcpyHostToDevice) ); + checkCuda( cudaMemcpy(i1_d, x1, dim1.tot()*sizeof(dnnType), cudaMemcpyHostToDevice) ); + checkCuda( cudaMemcpy(i2_d, x2, dim2.tot()*sizeof(dnnType), cudaMemcpyHostToDevice) ); + + // Inference + tk::dnn::dataDim_t dim; + net->infer(dim, nullptr); + + checkCuda( cudaMemcpy(deltaP.data(), o0_d, odim0.tot()*sizeof(dnnType), cudaMemcpyDeviceToHost) ); + checkCuda( cudaMemcpy(deltaQ.data(), o1_d, odim1.tot()*sizeof(dnnType), cudaMemcpyDeviceToHost) ); + } + +}; + +}} diff --git a/include/tkDNN/Layer.h b/include/tkDNN/Layer.h index 7e827d8..bfa3651 100644 --- a/include/tkDNN/Layer.h +++ b/include/tkDNN/Layer.h @@ -125,6 +125,7 @@ public: virtual layerType_t getLayerType() { return LAYER_INPUT; }; virtual dnnType* infer(dataDim_t &dim, dnnType* srcData) { + dim = output_dim; return dstData; } }; @@ -368,7 +369,8 @@ public: virtual dnnType* infer(dataDim_t &dim, dnnType* srcData); public: - Layer **layers; //ids of layers to be merged + static const int MAX_LAYERS = 32; + Layer *layers[MAX_LAYERS]; //ids of layers to be merged int layers_n; //number of layers }; diff --git a/include/tkDNN/utils.h b/include/tkDNN/utils.h index 3fa9d34..de85850 100644 --- a/include/tkDNN/utils.h +++ b/include/tkDNN/utils.h @@ -88,7 +88,7 @@ } \ } -void printCenteredTitle(const char *title, char fill, int dim); +void printCenteredTitle(const char *title, char fill, int dim = 30); bool fileExist(const char *fname); void readBinaryFile(std::string fname, int size, dnnType** data_h, dnnType** data_d, int seek = 0); int checkResult(int size, dnnType *data_d, dnnType *correct_d, bool device = true, int limit = 10); diff --git a/src/Route.cpp b/src/Route.cpp index f61335e..39bb14e 100644 --- a/src/Route.cpp +++ b/src/Route.cpp @@ -7,9 +7,15 @@ namespace tk { namespace dnn { Route::Route(Network *net, Layer **layers, int layers_n) : Layer(net) { - this->layers = layers; + // copy input layers + if(layers_n > MAX_LAYERS) { + FatalError("ROUTE: reached max number of input layers"); + } + for(int i=0; ilayers[i] = layers[i]; + } this->layers_n = layers_n; - + //get dims output_dim.l = 1; output_dim.c = 0; diff --git a/src/utils.cpp b/src/utils.cpp index 6789e8c..a5f46d0 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -53,8 +53,9 @@ void printDeviceVector(int size, dnnType* vec_d, bool device) dnnType *vec; if(device) { vec = new dnnType[size]; - cudaDeviceSynchronize(); - cudaMemcpy(vec, vec_d, size*sizeof(dnnType), cudaMemcpyDeviceToHost); + checkCuda(cudaDeviceSynchronize()); + checkCuda(cudaMemcpy(vec, vec_d, size*sizeof(dnnType), cudaMemcpyDeviceToHost)); + checkCuda(cudaDeviceSynchronize()); } else { vec = vec_d; } @@ -76,10 +77,11 @@ int checkResult(int size, dnnType *data_d, dnnType *correct_d, bool device, int if(device) { data_h = new dnnType[size]; correct_h = new dnnType[size]; - cudaDeviceSynchronize(); - cudaMemcpy(data_h, data_d, size*sizeof(dnnType), cudaMemcpyDeviceToHost); - cudaMemcpy(correct_h, correct_d, size*sizeof(dnnType), cudaMemcpyDeviceToHost); - + checkCuda(cudaDeviceSynchronize()); + checkCuda(cudaMemcpy(data_h, data_d, size*sizeof(dnnType), cudaMemcpyDeviceToHost)); + checkCuda(cudaMemcpy(correct_h, correct_d, size*sizeof(dnnType), cudaMemcpyDeviceToHost)); + checkCuda(cudaDeviceSynchronize()); + } else { data_h = data_d; correct_h = correct_d; diff --git a/tests/imuodom/imuodom.cpp b/tests/imuodom/imuodom.cpp index fc9f1b1..e9e98b8 100644 --- a/tests/imuodom/imuodom.cpp +++ b/tests/imuodom/imuodom.cpp @@ -1,5 +1,6 @@ #include #include "tkdnn.h" +#include "tkDNN/ImuOdom.h" const char *i0_bin = "../tests/imuodom/layers/input0.bin"; const char *i1_bin = "../tests/imuodom/layers/input1.bin"; @@ -18,8 +19,14 @@ const char *l1_bin = "../tests/imuodom/layers/bidirectional_4.bin"; const char *d0_bin = "../tests/imuodom/layers/dense_3.bin"; const char *d1_bin = "../tests/imuodom/layers/dense_4.bin"; + int main() { + tk::dnn::ImuOdom ImuNet; + ImuNet.init("../tests/imuodom/layers/"); + + const int N = 19513; + // Network layout tk::dnn::dataDim_t dim0(1, 4, 1, 100); tk::dnn::dataDim_t dim1(1, 3, 1, 100); @@ -28,56 +35,39 @@ int main() { // Load input dnnType *i0_d, *i1_d, *i2_d; dnnType *i0_h, *i1_h, *i2_h; - readBinaryFile(i0_bin, dim0.tot(), &i0_h, &i0_d); - readBinaryFile(i1_bin, dim1.tot(), &i1_h, &i1_d); - readBinaryFile(i2_bin, dim2.tot(), &i2_h, &i2_d); - - tk::dnn::Network net(dim0); - tk::dnn::Input x0 (&net, dim0, i0_d); - tk::dnn::Conv2d x0_0(&net, 128, 1, 11, 1, 1, 0, 0, c0_bin); - tk::dnn::Conv2d x0_1(&net, 128, 1, 11, 1, 1, 0, 0, c1_bin); - tk::dnn::Pooling x0_2(&net, 1, 3, 1, 3, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX); - - tk::dnn::Input x1 (&net, dim1, i1_d); - tk::dnn::Conv2d x1_0(&net, 128, 1, 11, 1, 1, 0, 0, c2_bin); - tk::dnn::Conv2d x1_1(&net, 128, 1, 11, 1, 1, 0, 0, c3_bin); - tk::dnn::Pooling x1_2(&net, 1, 3, 1, 3, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX); - - tk::dnn::Input x2 (&net, dim2, i2_d); - tk::dnn::Conv2d x2_0(&net, 128, 1, 11, 1, 1, 0, 0, c4_bin); - tk::dnn::Conv2d x2_1(&net, 128, 1, 11, 1, 1, 0, 0, c5_bin); - tk::dnn::Pooling x2_2(&net, 1, 3, 1, 3, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX); - - tk::dnn::Layer *concat_l[3] = { &x0_2, &x1_2, &x2_2 }; - tk::dnn::Route concat (&net, concat_l, 3); - - tk::dnn::LSTM lstm0(&net, 128, true, l0_bin); - tk::dnn::LSTM lstm1(&net, 128, false, l1_bin); - - tk::dnn::Dense d0 (&net, 3, d0_bin); - - tk::dnn::Layer *lstm1_l[1] = { &lstm1 }; - tk::dnn::Route lstm1_link (&net, lstm1_l, 1); - tk::dnn::Dense d1 (&net, 4, d1_bin); - net.print(); + readBinaryFile(i0_bin, dim0.tot()*N, &i0_h, &i0_d); + readBinaryFile(i1_bin, dim1.tot()*N, &i1_h, &i1_d); + readBinaryFile(i2_bin, dim2.tot()*N, &i2_h, &i2_d); dnnType *data; tk::dnn::dataDim_t dim; - TIMER_START - // Inference - data = net.infer(dim, data); - TIMER_STOP - - // Print real test - std::cout<<"\n==== CHECK RESULT ====\n"; dnnType *out0, *out1; dnnType *out0_h, *out1_h; - readBinaryFile(o0_bin, d0.output_dim.tot(), &out0_h, &out0); - readBinaryFile(o1_bin, d1.output_dim.tot(), &out1_h, &out1); - d0.output_dim.print(); - checkResult(d0.output_dim.tot(), d0.dstData, out0); - d1.output_dim.print(); - checkResult(d1.output_dim.tot(), d1.dstData, out1); + readBinaryFile(o0_bin, ImuNet.odim0.tot()*N, &out0_h, &out0); + readBinaryFile(o1_bin, ImuNet.odim1.tot()*N, &out1_h, &out1); + + for(int i=0; i