joaoleal / CppADCodeGen

Source Code Generation for Automatic Differentiation using Operator Overloading
Other
167 stars 37 forks source link

Save LinuxDynamicLib and corresponding model #57

Closed mohamdev closed 4 years ago

mohamdev commented 4 years ago

Hello,

First I want to thank you for code and your help. I actually have a problem. I would like to load a LinuxDynamicLib (lets call it myLib) and the corresponding model (lets call it myModel) at the beggining of my main(). And then, I want to send both as argument for different functions, to be able to use myModel inside those functions. In fact, for the moment, I have to load myLib and myModel, inside those functions, which takes pretty much time as myLib and myModel are loaded at every call of those functions. The code would run much faster if I instantiate only once myModel and myLib at the beggining of main(), and then send them as argument for the functions that need myModel.

To do so, I coded the following function to load myModel and myLib and save them:

LinuxDynamicLib<Scalar> loadLibrary(std::vector<std::unique_ptr<GenericModel<double>>> & models){

            LinuxDynamicLib<Scalar> myLib("./fkine_angular_IMU1.so");  //Instantiation of the dynamic library
            std::unique_ptr<GenericModel<double>> myModel = myLib.model("fkine_angular_IMU1"); //Instantiation of the model, from the dynamic library
            models.push_back(std::move(myModel));
            return myLib;
}

This function takes as input a std::vector of GenericModel<double>s, loads myLib, loads myModel, adds myModel to my vector models (which can contain several models from different libs), then returns myLib. Actually, I have to return myLib, otherwise myModel will be deleted. But when I do return myLib I get the following compilation error : error : use of deleted function 'cppAD::cg::LinuxDynamicLib<Base>::LinuxDynamicLib(const cppAD::cg::LinuxDynamicLib<Base>&) [with Base = double]' This error is actually pointing on the line return myLib.

I also have a note : declared here, which is pointing on LinuxDynamicLib(const LinuxDynamicLib&) = delete; code line, in linux_dynamiclib.hpp file.

Thank you very much for your help, I don't know if i'm misunderstanding someting, as i'm a begginer on C++. I wish you a nice day

joaoleal commented 4 years ago

Hello Adjel,

The function is returning a LinuxDynamicLib by value but this class has no copy or move constructor implemented. I can consider adding a move constructor to make it easier to return it from functions or move it as an argument to functions/methods.

You could return a smart pointer from your function instead:

std::unique_ptr<LinuxDynamicLib<Scalar>> loadLibrary(std::vector<std::unique_ptr<GenericModel<Scalar>>> & models){

        std::unique_ptr<LinuxDynamicLib<Scalar>> myLib(new LinuxDynamicLib<Scalar>("./fkine_angular_IMU1.so"));  //Instantiation of the dynamic library
        std::unique_ptr<GenericModel<Scalar>> myModel = myLib->model("fkine_angular_IMU1"); //Instantiation of the model, from the dynamic library
        models.push_back(std::move(myModel));
        return myLib;
    }

If you are using C++14 you may be insterested in using

auto myLib = std::make_unique<LinuxDynamicLib<Scalar>>("./fkine_angular_IMU1.so");
mohamdev commented 4 years ago

Thank you very much for your fast feedback, I will try this as soon as possible and tell you if it worked in my case

mohamdev commented 4 years ago

I just tried it and it worked wonderfully, thank you very much. By the way, when generating and compiling the DynamicLibrary, do you think that it's possible to add several models based on different ADfun in a single library ? Allowing me then to instantiate all my models from a single library this way :

        std::unique_ptr<LinuxDynamicLib<Scalar>> myLib(new LinuxDynamicLib<Scalar>("./nameMyLib.so"));  //Instantiation of the dynamic library
        std::unique_ptr<GenericModel<Scalar>> myModel1 = myLib->model("nameModel1");  //Instantiation model 1
        std::unique_ptr<GenericModel<Scalar>> myModel2 = myLib->model("nameModel2"); //Instantiation model 2
        std::unique_ptr<GenericModel<Scalar>> myModelN = myLib->model("nameModelN"); //Instantiation model N
joaoleal commented 4 years ago

This is already possible. You can add multiple models to a ModelLibraryCSourceGen by either adding them to the constructor:

ModelCSourceGen<double> model1(adFun1, "nameModel1");
ModelCSourceGen<double> model2(adFun2, "nameModel2");
ModelCSourceGen<double> model3(adFun3, "nameModel3");

ModelLibraryCSourceGen<double> modelLibGen(model1, model2, model3);

or afterwars:

ModelCSourceGen<double> model3(fun1, "nameModel3");
modelLibGen.addModel(model3);
mohamdev commented 4 years ago

It worked great ! Thank you very much for your fast feedback :) have a nice day