Project

General

Profile

Feature #951

Updated by Teemu Murtola about 7 years ago

One issue that surfaces now and then is to get rid of separate libraries for single and double precision. I haven't yet seen a concrete plan for it, so I'm creating this issue to keep the discussion (since it may be a long time since it actually gets implemented). I'll list some of the problems that need to be solved for this to happen. For the sake of clarity, I'll focus only on the single vs. double precision, MPI vs. no-MPI (or others) may have different problems (although some will likely be the same).

I've only seen people proposing some kind of dual compilation of the source files. Done naively (without any changes to the source), this leads to every function etc. appearing as a duplicate symbol, and things can't be linked. Alternatives to fix this while still keeping everything in one library:
# Add #ifdefs around each function declaration (proposed in #685). This has a major issue in that it would need to be done for _every_ function declaration, as well as for _every_ call site. Changing the #ifdef to a macro (e.g., GMX_FUNCTION(func_name)) doesn't change the need to change _every_ instance of each function.
# If everything is compiled as C++ without @extern "C"@, then functions with a @real@ argument will get different mangled names based on the precision. But there will still be duplicate symbols for functions that don't have @real@ arguments, as well as for class names. Additionally, anonymous namespaces can cause additional issues (I think they may result in symbols that are visible to the linker).
#
Use a similar approach as is done on some Microsoft libraries with respect to Unicode/non-Unicode, i.e., #define each class and function name to a different name based on the precision (e.g., @#define do_md do_mdS@ for single and @#define do_md do_mdD@ for double). Requires quite a lot of maintenance, but may be possible to automate...
# Don't know if there are some linker tricks that could be used to rename the symbols, but that is not going to be portable.
# If everything is compiled as C++ without @extern "C"@, then functions with a @real@ argument will get different mangled names based on the precision. But there will still be duplicate symbols for functions that don't have @real@ arguments, as well as for class names. Additionally, anonymous namespaces can cause additional issues (I think they may result in symbols that are visible to the linker).
#
With C++, we could perhaps also use different namespaces for the single and double precision versions, which might work. This would require only changing the top-level namespace declarations in headers and source files based on precision, but everything would first need to be put into these namespaces.
# We could also use C++ templates, where @real@ is a template argument. This solves most of the problems of the dual compilation approach, as we don't need to compile everything twice, and templates can be used also for class names. This is only manageable if we require compiler support for @extern template@, which is a C++11 feature (but there is hope for compiler support also on older compilers, as I think gcc has had it from 3.4 or something); without it, we would need to make most of Gromacs header-only...


If we only want to have both precisions in the same binary, but separate libraries is ok, we may get away without renaming the symbols. If the binary only needs a few entry points into the library (which will be the case if we do #685, see source:src/programs/g_ana/g_ana.cpp), then we could load dynamically load only one of the precision-dependent libraries. But this may get quite complex in practice, in particular if it needs to be portable...

The title is on purpose a bit vague to make room for discussing the different alternatives.

Back