Closed mdclemen closed 3 years ago
One would need to change the type for Number
and change the interfaces to external codes (BLAS, LAPACK, linear solver, ...) to convert between float and double.
It seems that in a number of interface files, there is mixed use of types defined in src/Common/IpTypes.h with double
and int
. For example in in src/Algorithms/LinearSolvers/IpPardisoSolverInterface.cpp/.hpp, in the class ESymSolverStatus PardisoSolverInterface::MultiSolve
has inputs:
(bool new_matrix, const Index* ia, const Index* ja, Index nrhs, double* rhs_vals, bool check_NegEVals, Index numberOfNegEVals)
It would seem reasonable that double
could be changed to Number
in most of these cases (since Index
is being used vice int
), and then the type of Number
can be controlled in IpTypes.h. Does this sound right, or am I missing something on why double
is hard coded here?
On this example, the method declaration has probably been taken from the upper class, which also uses double*
already (https://github.com/coin-or/Ipopt/blob/master/src/Algorithm/LinearSolvers/IpSparseSymLinearSolverInterface.hpp#L188). Also SparseSymLinearSolverInterface::GetValuesArrayPtr()
gives a double*
instead of a Number*
.
One argument why this could be intentionally is that the authors thought that linear solvers always use double-precision floating point numbers. So if there would be a code added to convert between Number
and double
, then that could be added once to the routines that call MultiSolve()
and fill the ValuesArray, instead of implementing this in every linear solver interface.
I've created a fork at https://github.com/mdclemen/Ipopt, that demonstrates single precision functionality (in case anyone else desires this functionality). Pardiso is the only solver I was easily able to update the interface for to use single precision. There is a configure option now, --enable-single-precision
, which enables single precision. I'm not sure this is anything you guys would like to add to the library, but if it is, I can submit a pull request.
That looks like a lot of work and a nice addition that could potentially be useful to others, too.
I'm ok with all the changes from double
to Number
, but wonder whether the distinction for every fabs
, pow
, sqrt
is necessary. It looks to me as if std::pow
is also available for float (https://en.cppreference.com/w/cpp/numeric/math/pow), so function overloading could be used here. Also powf
introduces dependency on C++11.
If one does all the effort to get Ipopt working also with Number=float
, then it would be nice to make it simpler to add support for other typedefs for Number
in the future, too.
Valid points. I have removed calls to precision specific math functions and am using the overloaded functions. I builds for me without complaining.
I have also asked HSL if they can give me the single precision source files for their solvers so I can try to write interfaces for those.
Thank you! A pull request would be great.
Some more TODOs:
--with-precision=single
(ASL, MA28, Java interface, WSMP, single precision HSL, etc)I would consider this done for now.
All changes are shown in https://github.com/coin-or/Ipopt/compare/master...a21c9af3cf2a6f117136c5bb158872dfb76b181c Note in particular the updates to CHANGELOG and documentation.
HSL has sent me a beta version of coinhsl that includes single precision codes. @svigerske would you be interested in testing it out?
yes, I can try
They seem to work fine. I updated Ipopt/devel in 5694ddfa1a17cabf65e1c84c45cc9caeab0be1f0.
Hi, just as a follow-up question since I'm trying to incorporate single precision floating number computation.
I have compiled Ipopt with option --with-precision=single
. But it returns the error:
Exception of type: DYNAMIC_LIBRARY_FAILURE in file "../../src/Common/IpLibraryLoader.cpp" at line 198:
Exception message: /usr/local/lib/libhsl.so: undefined symbol: MA57A
EXIT: Library loading failure.
It seems like I did not get the correct versions of HSL libraries. I wonder if anyone knows what I should do on the HSL side?
HSL only provides me ma57d.f
and ma57s.f
in their source code, which seem to be the double precision version and the single precision version, respectively. So I'm not sure what MA57A
means here. Maybe there is a similar ma57a.f
?
I would appreciate any help!
ma57s.f
defines a subroutine MA57A
, at least in my coinhsl version from 2021.5.5.
Maybe your build of the HSL library missed compiling ma57s.f
.
(The double precision version of MA57A
is called MA57AD
and implemented in ma57d.f
.)
What would it take to make a single precision (32 bit floating point) version of IPOPT?