Replace the use of OpenCL kernels with API calls for copies of rectangular buffers#1169
Conversation
stan/math/opencl/matrix_cl.hpp
Outdated
| ncols, A.rows(), A.cols(), this->rows(), | ||
| this->cols(), triangular_view); | ||
| if (triangular_view == TriangularViewCL::Entire) { | ||
| cl::size_t<3> src_offset; |
There was a problem hiding this comment.
I could find a way to initialize this cl::size_t vectors in a shorter manner :/
There was a problem hiding this comment.
Hah. this is a silly problem with their API it seems. I think the general purpose solution is something like:
template <typename Arg, typename... Ts, typename std::enable_if<std::is_integral<Arg>::value>::type * = nullptr>
auto to_size_t(Arg a, Ts... all) {
constexpr size_t len = sizeof...(Ts)+1;
int values[len] = {a, all...};
cl::size_t<len> s;
for (size_t i = 0; i < len; i++)
s[i] = values[i];
return s;
}(we do all the variadic weirdness to make sure we're getting ints at compile time).
this one is a little hackier and if you wanted to pass more than three, you'd have to specify a template parameter. But it's much less confusing imo and is probably fine forever for us:
template <int len=3>
cl::size_t<len> to_size_t(std::vector<int> values) {
assert(values.size() ==len);
cl::size_t<len> s;
for (size_t i = 0; i < len; i++)
s[i] = values[i];
return s;
}Called like this:
int main() {
cl::size_t<3> s = to_size_t({1, 2, 3});
return s[0];
}There was a problem hiding this comment.
Thanks Sean!! I am going to try and incorporate the second one today, I thinks this one is going to be fine forever, for sure :)
|
The benchmark file: https://gist.github.com/rok-cesnovar/a9e7196bcd0730f29ca2591f54fd3a10 |
seantalts
left a comment
There was a problem hiding this comment.
This looks great. Just put a comment for a possible semi-improvement on specifying cl::size_t; up to you if you think something like that is worth implementing here.
…gs/RELEASE_500/final)
|
I added the |
|
@seantalts sooo, this one is weird. on a routine This also happens on develop, although not on Jenkins apparently. So I thought it must be g++. clang then gave this error: Google told me to add So the extra weird is that this passed Jenkins, and this exact same code compiles with every other test Am I missing something? If not, what is the process here? Revert this PR or open a new one that fixes this? Anyways, I apologize... |
|
I had thought we'd decided not to include C-style asserts in any of our code. If that test is to catch user errors, it should throw rather than assert. If it's there to catch programmer errors, it should be replaced with unit tests. Hopefully, @syclik and @seantalts will weigh in on policy and correct me if I'm misremembering. |
|
I haven't heard about the assert policy. This one is to help developers and I'm not sure how to replace it with unit tests. |
I think we should roll forward since the build isn't broken. Bob, what would you do here? We're just creating a simple helper function that creates a |
|
I think we should roll forward since the build isn't broken. Bob, what would you do here? We're just creating a simple helper function that creates a cl::size_t, which is kind of an annoying type to create. We talked about two solutions here: #1169 (comment) one of which is fairly complicated templating that is always correct and doesn't have an assert, and the other is simpler but has an assert. Is there a way to get rid of the assert there? Or should we go with the full template solution? or some other thing?
The problem with asserts is that they can catch programmer error, but their only behavior at runtime is to crash the environment (and report which asssert failed). Do you anticipate the assert being triggered at runtime? If so, I'd suggest throwing an exception instead, and if not, I'd suggest removing it since it's not doing anything.
|
|
I don't anticipate it happening at runtime but I do anticipate it happening during development... |
|
I think Bob’s remembering right. I don’t think we ever came up with an
explicit policy, but we haven’t had a good example where we needed to use
an assert where a runtime exception would have functioned more
appropriately.
Currently, if code asserts, what’s the downstream effect? RStan would just
crash? Would R crash too? Or would it treat it like an error and move on?
…On Thu, Mar 21, 2019 at 5:12 PM Bob Carpenter ***@***.***> wrote:
> I think we should roll forward since the build isn't broken. Bob, what
would you do here? We're just creating a simple helper function that
creates a cl::size_t, which is kind of an annoying type to create. We
talked about two solutions here: #1169 (comment) one of which is fairly
complicated templating that is always correct and doesn't have an assert,
and the other is simpler but has an assert. Is there a way to get rid of
the assert there? Or should we go with the full template solution? or some
other thing?
The problem with asserts is that they can catch programmer error, but
their only behavior at runtime is to crash the environment (and report
which asssert failed). Do you anticipate the assert being triggered at
runtime? If so, I'd suggest throwing an exception instead, and if not, I'd
suggest removing it since it's not doing anything.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1169 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAZ_F8YP_0GSON-IB09yPndXXFavQY8lks5vY_WxgaJpZM4cALRe>
.
|
|
Do we have an exception we use for Stan developer error? I guess we could use that? Or else just code it the dumb way for the specific case of 3 inputs: auto to_size_t(int a, int b, int c) {
cl::size_t<3> s;
s[0] = a;
s[1] = b;
s[2] = c;
return s;
}
int main() {
cl::size_t<3> s = to_size_t(1, 2, 3);
return s[0];
} |
|
So far, we've been squeezing our exceptions into things that subclass It's been ok, but there's no reason we can't define our own subclass. I haven't followed the content of where this came up from, so I don't have a good suggestion. Hopefully one of them makes sense. If not, create one that's sensible? |
|
I'm going to put up a PR changing it to the correct-but-complicated templated version, above. If we have a policy on assert, maybe we can add a test for it as well similar to the math dependencies one? |
|
Still weirded out about why it passed on Jenkins before:
Rok did you figure out why? The "Full Unit with GPU" tests run on every pull request now, so I don't think that's it...? |
|
Let me know if you want extra eyes on it. (Just tag me if you need it.) |
|
@seantalts unfortunately no. this doesnt error out on this branch This failed on Sebastian's PR: The other difference that in this PR it was on the Always run part 1, on the other PR it was Always run part 2. Not sure if that makes any difference. |
Summary
This replaces the use of OpenCL kernels with the API calls for rectangular buffers. For triangular copies the kernels are still faster than API+
zeros()kernel. See #1168 for benchmark results. Will post the benchmarks for triangular copies in a reply below.Tests
/
Side Effects
/
Checklist
Math issue Replace OpenCL buffer rectangular copies in kernels with API calls #1168
Copyright holder: Rok Češnovar, Univ. of Ljubljana
the basic tests are passing
the code is written in idiomatic C++ and changes are documented in the doxygen
the new changes are tested