Improved thrust interop tutorial.
This commit is contained in:
@@ -6,20 +6,10 @@
|
||||
#include <thrust/iterator/counting_iterator.h>
|
||||
#include <thrust/device_ptr.h>
|
||||
|
||||
template<typename T> struct
|
||||
CV_TYPE
|
||||
{
|
||||
static const int DEPTH;
|
||||
};
|
||||
|
||||
template<> static const int CV_TYPE<float>::DEPTH = CV_32F;
|
||||
template<> static const int CV_TYPE<double>::DEPTH = CV_64F;
|
||||
template<> static const int CV_TYPE<int>::DEPTH = CV_32S;
|
||||
template<> static const int CV_TYPE<uchar>::DEPTH = CV_8U;
|
||||
template<> static const int CV_TYPE<char>::DEPTH = CV_8S;
|
||||
template<> static const int CV_TYPE<ushort>::DEPTH = CV_16U;
|
||||
template<> static const int CV_TYPE<short>::DEPTH = CV_16S;
|
||||
|
||||
/*
|
||||
@Brief step_functor is an object to correctly step a thrust iterator according to the stride of a matrix
|
||||
*/
|
||||
//! [step_functor]
|
||||
template<typename T> struct step_functor : public thrust::unary_function<int, int>
|
||||
{
|
||||
int columns;
|
||||
@@ -41,7 +31,8 @@ template<typename T> struct step_functor : public thrust::unary_function<int, in
|
||||
return idx;
|
||||
}
|
||||
};
|
||||
|
||||
//! [step_functor]
|
||||
//! [begin_itr]
|
||||
/*
|
||||
@Brief GpuMatBeginItr returns a thrust compatible iterator to the beginning of a GPU mat's memory.
|
||||
@Param mat is the input matrix
|
||||
@@ -52,11 +43,13 @@ thrust::permutation_iterator<thrust::device_ptr<T>, thrust::transform_iterator<s
|
||||
{
|
||||
if (channel == -1)
|
||||
mat = mat.reshape(1);
|
||||
CV_Assert(mat.depth() == CV_TYPE<T>::DEPTH);
|
||||
CV_Assert(mat.depth() == cv::DataType<T>::depth);
|
||||
CV_Assert(channel < mat.channels());
|
||||
return thrust::make_permutation_iterator(thrust::device_pointer_cast(mat.ptr<T>(0) + channel),
|
||||
thrust::make_transform_iterator(thrust::make_counting_iterator(0), step_functor<T>(mat.cols, mat.step / sizeof(T), mat.channels())));
|
||||
}
|
||||
//! [begin_itr]
|
||||
//! [end_itr]
|
||||
/*
|
||||
@Brief GpuMatEndItr returns a thrust compatible iterator to the end of a GPU mat's memory.
|
||||
@Param mat is the input matrix
|
||||
@@ -67,8 +60,11 @@ thrust::permutation_iterator<thrust::device_ptr<T>, thrust::transform_iterator<s
|
||||
{
|
||||
if (channel == -1)
|
||||
mat = mat.reshape(1);
|
||||
CV_Assert(mat.depth() == CV_TYPE<T>::DEPTH);
|
||||
CV_Assert(mat.depth() == cv::DataType<T>::depth);
|
||||
CV_Assert(channel < mat.channels());
|
||||
return thrust::make_permutation_iterator(thrust::device_pointer_cast(mat.ptr<T>(0) + channel),
|
||||
thrust::make_transform_iterator(thrust::make_counting_iterator(mat.rows*mat.cols), step_functor<T>(mat.cols, mat.step / sizeof(T), mat.channels())));
|
||||
}
|
||||
}
|
||||
//! [end_itr]
|
||||
|
||||
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <thrust/random.h>
|
||||
#include <thrust/sort.h>
|
||||
#include <thrust/system/cuda/execution_policy.h>
|
||||
//! [prg]
|
||||
struct prg
|
||||
{
|
||||
float a, b;
|
||||
@@ -22,36 +23,10 @@ struct prg
|
||||
return dist(rng);
|
||||
}
|
||||
};
|
||||
//! [prg]
|
||||
|
||||
template<typename T> struct pred_eq
|
||||
{
|
||||
T value;
|
||||
int channel;
|
||||
__host__ __device__
|
||||
pred_eq(T value_, int channel_ = 0) :value(value_), channel(channel_){}
|
||||
__host__ __device__
|
||||
bool operator()(const T val) const
|
||||
{
|
||||
return val == value;
|
||||
}
|
||||
template<int N>
|
||||
__host__ __device__ bool operator()(const cv::Vec<T, N>& val)
|
||||
{
|
||||
if (channel < N)
|
||||
return val.val[channel] == value;
|
||||
return false;
|
||||
}
|
||||
|
||||
__host__ __device__ bool operator()( const thrust::tuple<T, T, T>& val)
|
||||
{
|
||||
if (channel == 0)
|
||||
return thrust::get<0>(val) == value;
|
||||
if (channel == 1)
|
||||
return thrust::get<1>(val) == value;
|
||||
if (channel == 2)
|
||||
return thrust::get<2>(val) == value;
|
||||
}
|
||||
};
|
||||
//! [pred_greater]
|
||||
template<typename T> struct pred_greater
|
||||
{
|
||||
T value;
|
||||
@@ -61,12 +36,14 @@ template<typename T> struct pred_greater
|
||||
return val > value;
|
||||
}
|
||||
};
|
||||
//! [pred_greater]
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Generate a 2 channel row matrix with 100 elements. Set the first channel to be the element index, and the second to be a randomly
|
||||
// generated value. Sort by the randomly generated value while maintaining index association.
|
||||
//! [sort]
|
||||
{
|
||||
cv::cuda::GpuMat d_idx(1, 100, CV_32SC2);
|
||||
|
||||
@@ -82,8 +59,10 @@ int main(void)
|
||||
|
||||
cv::Mat h_idx(d_idx);
|
||||
}
|
||||
//! [sort]
|
||||
|
||||
// Randomly fill a row matrix with 100 elements between -1 and 1
|
||||
//! [random]
|
||||
{
|
||||
cv::cuda::GpuMat d_value(1, 100, CV_32F);
|
||||
auto valueBegin = GpuMatBeginItr<float>(d_value);
|
||||
@@ -92,8 +71,10 @@ int main(void)
|
||||
|
||||
cv::Mat h_value(d_value);
|
||||
}
|
||||
//! [random]
|
||||
|
||||
// OpenCV has count non zero, but what if you want to count a specific value?
|
||||
//! [count_value]
|
||||
{
|
||||
cv::cuda::GpuMat d_value(1, 100, CV_32S);
|
||||
d_value.setTo(cv::Scalar(0));
|
||||
@@ -101,18 +82,24 @@ int main(void)
|
||||
auto count = thrust::count(GpuMatBeginItr<int>(d_value), GpuMatEndItr<int>(d_value), 15);
|
||||
std::cout << count << std::endl;
|
||||
}
|
||||
//! [count_value]
|
||||
|
||||
// Randomly fill an array then copy only values greater than 0. Perform these tasks on a stream.
|
||||
//! [copy_greater]
|
||||
{
|
||||
cv::cuda::GpuMat d_value(1, 100, CV_32F);
|
||||
auto valueBegin = GpuMatBeginItr<float>(d_value);
|
||||
auto valueEnd = GpuMatEndItr<float>(d_value);
|
||||
cv::cuda::Stream stream;
|
||||
//! [random_gen_stream]
|
||||
thrust::transform(thrust::system::cuda::par.on(cv::cuda::StreamAccessor::getStream(stream)), thrust::make_counting_iterator(0), thrust::make_counting_iterator(d_value.cols), valueBegin, prg(-1, 1));
|
||||
//! [random_gen_stream]
|
||||
int count = thrust::count_if(thrust::system::cuda::par.on(cv::cuda::StreamAccessor::getStream(stream)), valueBegin, valueEnd, pred_greater<float>(0.0));
|
||||
cv::cuda::GpuMat d_valueGreater(1, count, CV_32F);
|
||||
thrust::copy_if(thrust::system::cuda::par.on(cv::cuda::StreamAccessor::getStream(stream)), valueBegin, valueEnd, GpuMatBeginItr<float>(d_valueGreater), pred_greater<float>(0.0));
|
||||
cv::Mat h_greater(d_valueGreater);
|
||||
}
|
||||
//! [copy_greater]
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user