Improved thrust interop tutorial.

This commit is contained in:
Dan
2015-09-16 12:03:35 -04:00
parent 09d392f09d
commit 23fc5930b7
4 changed files with 104 additions and 47 deletions

View File

@@ -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]

View File

@@ -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;
}