-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Fix the dependency on cube and mat from arma #3585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Omar Shrit <[email protected]>
| y = arma::max(y, x); | ||
| y.set_size(size(x)); | ||
| y.zeros(); | ||
| y = max(y, x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest to change y = max(y, x) to y = arma::max(y, x).
C++ is notorious for problems involved with Argument Dependent Lookup (ADL). For example, the compiler may viably think that max(y,x) is supposed to mean std::max(y,x), and then spit out an error, complaining that std::max() doesn't know what to do with the arguments.
Placing the arma:: namespace qualification ensures that only max() from Armadillo is meant here.
The rules for ADL are quite byzantine and easily abused: https://en.cppreference.com/w/cpp/language/adl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally removed the arma because I do not see another way of using this function with coot.
Do you have a solution for this problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The longer-term aim here is to be able to use Armadillo or Bandicoot with the same mlpack code. After all, the linear algebraic operations themselves live at a higher level of abstraction than the details of how the matrices are stored (for the most part). That has been our goal for several years, and ADL is the only reasonable way to accomplish this. Although there are some warts with ADL, and it is complicated and routinely criticized, it is hard to see how it can go wrong for something like this.
If you have max(y, x) where y and x are objects from the arma:: namespace, then arma:: is added to the list of namespaces that are searched for the best match for max(), and everything works fine. If it does not work fine, and the user has not done anything "malicious" like adding other matching overloads that can cause the compiler to hiccup (which they shouldn't be doing anyway!), then the issue is a compiler bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to provide an overloaded function specialised for Bandicoot matrices, possibly within an #ifdef MLPACK_USE_BANDICOOT guard:
static void Fn(const coot::Mat<eT>& x, coot::Mat<eT>& y)
The function would contain a call to coot::max(). It's perfectly fine to have both Armadillo and Bandicoot implementations of Fn() available at the same time.
In my experience it's less painful to not rely on ADL. Here's an example of ADL weirdness from ~5 years ago: https://gitlab.com/conradsnicta/armadillo-code/-/issues/94
Within Armadillo, the max() function is implemented using template restrictors, which may have unintended interactions with ADL voodoo:
https://gitlab.com/conradsnicta/armadillo-code/-/blob/12.6.x/include/armadillo_bits/fn_max.hpp?ref_type=heads#L73-92
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but what I am getting at is that without ADL, every single linear algebra expression inside mlpack will need to have duplicate Bandicoot and Armadillo implementations. That's a massive amount of extra code to maintain and keep up to date---it's not realistic.
If we have to make exceptions explicitly for min() and max() and size() (due to the naming conflicts with std:: functionality), that's fine, but the way to do that would be to have an mlpack-local min() and max() implementation that redirect to the correct Armadillo/Bandicoot implementations instead of using ADL. But for the rest of the functionality in those libraries (e.g., say, repmat() or repelem() or eig_sym() or whatever), ADL should suffice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I also suspect that the main problem is interference from functions defined in the std namespace. Besides the usual suspects (min(), max(), size()) there are also other std functions that have same name as arma functions: clamp(), abs(), arg(), etc.
|
Overall, I'd suggest to keep the original version of the code (ie. separate functions for Mat and Cube), as it's clear in its intent. Anytime template arguments are more general (either by adding template args or replacing existing ones), it takes longer for compiler to try out various possible instantiations of the function. This increases compilation time and memory use. Having two separate functions is less work for the compiler in this case. |
|
I don't mind replacing the implementation as it will also work with Bandicoot; however, we do need to figure out the Windows build issue first. I am wondering if the build failure is a result of MSVC defining |
Armadillo undefines any Alternatively, it's possible that the un-definitions of |
Signed-off-by: Omar Shrit <[email protected]>
Yeah, unfortunately, I think you are right; even with a Based on my read of the ADL rules, the MSVC compiler is in the wrong here, but I don't think I am going to go through the effort to actually report that. Their team has actually been responsive to Armadillo and mlpack related bugs in the past (at one point, not sure if it is still true, mlpack itself was a part of their compiler test suite). |
Signed-off-by: Omar Shrit <[email protected]>
rcurtin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, it works! I see this uses the MLPACK_HAS_COOT macro which I don't think is defined anywhere, but I am sure we will add configuration for it soon enough. Anyway, just some small little comments before merge. 👍
src/mlpack/methods/ann/activation_functions/rectifier_function.hpp
Outdated
Show resolved
Hide resolved
Co-authored-by: Ryan Curtin <[email protected]>
|
@rcurtin very good will apply these so we can merge it tomorrow, |
Signed-off-by: Omar Shrit <[email protected]>
Signed-off-by: Omar Shrit <[email protected]>
In reality, we do not need to have an overload per matrix type, in fact, these two functions can be merged in one function. that is independent from the arma