gpufit / Gpufit

GPU-accelerated Levenberg-Marquardt curve fitting in CUDA
MIT License
312 stars 92 forks source link

Additional parameters for gpufit() via function overloading not possible if we use "extern C" #39

Open mscipio opened 6 years ago

mscipio commented 6 years ago

With reference to issue #30 I have been trying lately to add an optional parameter to gpufit that is able to give you the output of the fitting in terms of time curve, that you can compare to your original data to assess also visually the quality of the result.

After some trying, I managed to find a (imho) nice way to do it through overloading of some class init function, so that, depending on the number of parameters you use when calling gpufit(), the library can understand if you want to have the output of the fitting, as well, or just the standard output argument (params, number of iterations, and so on ...)

I am having just one problem in doing it: I can overload every function I need to, and this approach is working well, a part from the actual gpufit() function!

This is due to gpufit being exposed as a C interface:

#ifdef __cplusplus
extern "C" {
#endif

Given that function overloading is a specific property of C++, you cannot use it if you want to treat gpufit() as a C function. So far I used a workaraound based on using a different alias for the gpufit() function, in case I want to call it with the additional output_data parameter. But I don't like it ...

Two questions: 1- why do you need to do the extern "C" around gpufit()? Is it required by external bindings like python or matlab? 2- if this "extern" is actually needed, do you have any idea of alternative ways to use function overloading inside the extern "C" environment?

Thanks!

jkfindeisen commented 6 years ago

Is it required by external bindings like python or matlab?

Yes. For a good discussion see https://stackoverflow.com/questions/16730284/dll-written-in-c-vs-the-same-written-in-c

You could have additionally a C++ interface but only if you use the same compiler for your own project. The bindings like Python and Matlab will be limited to the extern "C" calling convention.

do you have any idea of alternative ways to use function overloading inside the extern "C" environment?

I think there are none afaik.

jkfindeisen commented 6 years ago

Btw. one workaround is SWIG. It can generate interfaces of C++ classes automatically that work as Python or Java classes but internally it uses a C interface, just automatically creates all the functions you wanted to create manually. It's support for templates is probably very limited.

See http://swig.org/Doc3.0/SWIGPlus.html#SWIGPlus

jkfindeisen commented 6 years ago

Another example of someone trying to use C++ class in Matlab for example. The idea would be the same for Python, C#, Java, .... He uses indices to a list as handles to identify classes which cannot cross the barrier. What you can do with a C interface is really, very restricted. Not even exceptions pass.

https://github.com/chappjc/MATLAB/tree/master/cppClass

mscipio commented 6 years ago

Thanks a lot for all the links. Working on this is becoming really instructive for me! :)

That means that, for the time being, I will decide between a separate function named slightly different than gpufit(), or an additional bool parameter with a default value (if possible in C interface) for the original gpufit() function, in order to call the other overloaded versions of class initializations ...

superchromix commented 6 years ago

We will look at this possibility. Having an alternate function call may be a viable solution.

mscipio commented 6 years ago

I solved it using just an optional parameter to gpufit() that is defined as a pointer float * output_data but takes value NULL as default. This is used internally as a flag to the to LMFit::get_results which data we want to transfer from GPU to CPU, keeping everything transparent if I want to keep calling gpufit() with the original 16 parameters.

If you are curious about it feel free to check my last commit to my fork!

caowencai commented 6 years ago

@mscipio Also at sometimes, the output_parameters is less important than output_data through integral or differential by the fitted model. Under this condition, it is to save some time between GPU and CPU by hiding the output_parameters or other parameters.

superchromix commented 6 years ago

Leaving this issue open as a reminder that extending the Gpufit interface to return function values could be an option in a future release.