问题
I want to use thrust::reduce
on a thrust::host_vector
of thrust::tuple<double,double>
. Because there is no predefined thrust::plus<thrust::tuple<double,double>>
I wrote my own and used the variant of thrust::reduce
with four arguments.
Since I'm a good citizen I put my custom version of plus
in my own namespace where I left the primary template simply undefined and specialized it for thrust::tuple<T...>
.
#include <iostream>
#include <tuple>
#include <thrust/host_vector.h>
#include <thrust/reduce.h>
#include <thrust/tuple.h>
namespace thrust_ext {
namespace detail {
// https://stackoverflow.com/a/24481400
template <size_t ...I>
struct index_sequence {};
template <size_t N, size_t ...I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};
template <size_t ...I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};
template < typename... T, size_t... I >
__host__ __device__ thrust::tuple<T...> plus(thrust::tuple<T...> const &lhs,
thrust::tuple<T...> const &rhs,
index_sequence<I...>) {
return {thrust::get<I>(lhs) + thrust::get<I>(rhs) ...};
}
} // namespace detail
template < typename T >
struct plus;
template < typename... T >
struct plus < thrust::tuple<T...> > {
__host__ __device__ thrust::tuple<T...> operator()(thrust::tuple<T...> const &lhs,
thrust::tuple<T...> const &rhs) const {
return detail::plus(lhs,rhs,detail::make_index_sequence<sizeof...(T)>{});
}
};
} //namespace thrust_ext
int main() {
thrust::host_vector<thrust::tuple<double,double>> v(10, thrust::make_tuple(1.0,2.0));
auto r = thrust::reduce(v.begin(), v.end(),
thrust::make_tuple(0.0,0.0),
thrust_ext::plus<thrust::tuple<double,double>>{});
std::cout << thrust::get<0>(r) << ' ' << thrust::get<1>(r) << '\n';
}
However, this does not compile. The error message is horribly long, see this Gist. The error message indicates that the problem is in some implementation detail of thrust::reduce
. Also, if I substitute thrust::tuple
with std::tuple
it compiles and runs as expected.
I'm using Thrust 1.8.1 with Clang 6.
回答1:
As you can see in your error message, thrust::tuple<double,double>
is actually
thrust::tuple<double, double, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type>
This is a C++03-style "variadic template" based on default template arguments, which means that sizeof...(T)
will count all the null_type
s and produce the wrong size (always 10).
You'll need to use thrust::tuple_size
to retrieve the actual size.
来源:https://stackoverflow.com/questions/48981446/thrust-reduce-with-tuple-accumulator