-
Notifications
You must be signed in to change notification settings - Fork 17
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
A couple of improvements for VexCL utilities #7
Conversation
ddemidov
commented
Jul 20, 2013
- Avoid creating temporaries for vex::max expressions
- Specify queue list when resizing vex::vectors
vex::max returns a lightweight expression. Let's return it directly instead of creating a temporary vector object.
vex::vector allows resizing without this, but it will use the vex::Context instance that was created last. In some cases this could be wrong.
Good fix and good idea; thanks! I'm not sure how I missed that missing queue list. Maybe it should be possible to disable VexCL's default-queue-list methods & arguments by setting some -DVEXCL_NO_DEFAULT_QUEUE type define? We do something similar in libMesh: novice users and old codes can default to MPI COMM_WORLD, but more robust codes can be tested against a --disable-default-comm-world configured library to give a compile-time error if they accidentally try to use that default. libMesh/libmesh#85 Where we really need to be returning auto is in many of the Antioch routines themselves; I've been holding off on that sweeping edit until we get some newer GPUs with which to benchmark any change in speed. That's going to be complicated by the need to maintain C++2003 compatibility for non-VexCL users, though. I'm currently leaning toward "AUTO_OR(other_return_type)" and "RETURN_DECLTYPE(expression)" macros with different definitions depending on whether ANTIOCH_HAVE_CXX11 is set. Hmm... and in fact, I'd need to do that right now, too, before I can pull this. I wonder if I can just get rid of our std::max(vex) override and rely on Koenig lookup finding vex::max() when appropriate? I think we've replaced all the "std::max(a,b)" with "using std::max(); max(a,b)" by now. And... no luck. g++ 4.7.3 tries to use std::max() anyway, which then fails. I'll see if I can figure out the lookup issues and/or add those auto/decltype macros later today. |
That would be easy to do, and it seems useful for library developers, so
Vexcl needs c++11 anyway, so probably this particular change is safe
I'll try to look at this issue next week. Can you specify a particular
|
Forgot to do this in bc23e0d
If macro VEXCL_NO_STATIC_CONTEXT_CONSTRUCTORS is defined, then all constructors that depend on vex::current_context() are disabled. references libantioch/antioch#7, libantioch/antioch#8
Regarding ADL failure: I give up. |
Regarding ADL failure: is it possible that vex::max(T a, T b) is only defined for vex::vector_expression or some such data type that requires implicit conversion from vex::vector? If so then I think we'd actually expect std::max(vex::vector, vex::vector) to be preferred. Koenig lookup adds vex::max to the set of overloads to be considered, but overload resolution then still prefers an exact match over a match which requires a conversion. |
#include <algorithm>
namespace NS {
struct S {};
template <class T>
T max(const T& a, const T& b) {
return a;
}
}
int main() {
using std::max;
NS::S a, b, c = max(a, b);
} So it seems there is another layer of problems with this issue. |
Ah, but #include <algorithm>
namespace NS {
struct S {};
template <class T1, class T2> // <-- Here is the change
T1 max(const T1& a, const T2& b) {
return a;
}
}
int main() {
using std::max;
NS::S a, b, c = max(a, b);
} |
Is that the situation with vex::max? Independent template typenames for the two arguments? |
It is. I can get different types for |
Naturally. Now I'm not sure why I've never run into this in my own code. I typically have specialized max(MyType,MyType); does that get preferred over the real std:: in the max(MyType,MyType) case? |
Hmm, with the following I get #include <algorithm>
namespace NS {
template <class T> struct S {};
template <class T1, class T2>
S<T1> max(const S<T1>& a, const S<T2>& b) {
return a;
}
}
int main() {
using std::max;
NS::S<int> a, b, c = max(a, b);
} |
Quick grep through antioch code showed that its always |
And there is no ambiguity here (it compiles fine): #include <algorithm>
namespace NS {
template <class T> struct S {};
template <class T>
S<T> max(const S<T>& a, const S<T>& b) {
return a;
}
}
int main() {
using std::max;
NS::S<int> a, b, c = max(a, b);
} |
So |
You'll probably need an |
Hmm... not quite. The infrastructure is there now for doing max properly but we're not hitting it yet. Plus I keep forgetting to cherry-pick the queue list bugfix. I'll get those now. |
Actually, we are now doing max as well as this patch does - assuming the inputs are full vex::vector objects, but returning an auto expression template where possible. That's only part way towards doing max (and other functions) properly, though - we really want to be able to accept any expression template as inputs too. I haven't yet settled on how to write template functions which match all possible template expressions from one library but which don't end up creating ambiguous matches with objects and expressions from another library. Our switch to "Antioch::ant_foo()" shims might make that much easier now though. But that ought to be a new issue; I think we're up to speed on this one. |