main.cu 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include "Thrust_interop.hpp"
  2. #include <opencv2/core/cuda_stream_accessor.hpp>
  3. #include <thrust/transform.h>
  4. #include <thrust/random.h>
  5. #include <thrust/sort.h>
  6. #include <thrust/system/cuda/execution_policy.h>
  7. //! [prg]
  8. struct prg
  9. {
  10. float a, b;
  11. __host__ __device__
  12. prg(float _a = 0.f, float _b = 1.f) : a(_a), b(_b) {};
  13. __host__ __device__
  14. float operator()(const unsigned int n) const
  15. {
  16. thrust::default_random_engine rng;
  17. thrust::uniform_real_distribution<float> dist(a, b);
  18. rng.discard(n);
  19. return dist(rng);
  20. }
  21. };
  22. //! [prg]
  23. //! [pred_greater]
  24. template<typename T> struct pred_greater
  25. {
  26. T value;
  27. __host__ __device__ pred_greater(T value_) : value(value_){}
  28. __host__ __device__ bool operator()(const T& val) const
  29. {
  30. return val > value;
  31. }
  32. };
  33. //! [pred_greater]
  34. int main(void)
  35. {
  36. // 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
  37. // generated value. Sort by the randomly generated value while maintaining index association.
  38. //! [sort]
  39. {
  40. cv::cuda::GpuMat d_data(1, 100, CV_32SC2);
  41. // Thrust compatible begin and end iterators to channel 1 of this matrix
  42. auto keyBegin = GpuMatBeginItr<int>(d_data, 1);
  43. auto keyEnd = GpuMatEndItr<int>(d_data, 1);
  44. // Thrust compatible begin and end iterators to channel 0 of this matrix
  45. auto idxBegin = GpuMatBeginItr<int>(d_data, 0);
  46. auto idxEnd = GpuMatEndItr<int>(d_data, 0);
  47. // Fill the index channel with a sequence of numbers from 0 to 100
  48. thrust::sequence(idxBegin, idxEnd);
  49. // Fill the key channel with random numbers between 0 and 10. A counting iterator is used here to give an integer value for each location as an input to prg::operator()
  50. thrust::transform(thrust::make_counting_iterator(0), thrust::make_counting_iterator(d_data.cols), keyBegin, prg(0, 10));
  51. // Sort the key channel and index channel such that the keys and indecies stay together
  52. thrust::sort_by_key(keyBegin, keyEnd, idxBegin);
  53. cv::Mat h_idx(d_data);
  54. }
  55. //! [sort]
  56. // Randomly fill a row matrix with 100 elements between -1 and 1
  57. //! [random]
  58. {
  59. cv::cuda::GpuMat d_value(1, 100, CV_32F);
  60. auto valueBegin = GpuMatBeginItr<float>(d_value);
  61. auto valueEnd = GpuMatEndItr<float>(d_value);
  62. thrust::transform(thrust::make_counting_iterator(0), thrust::make_counting_iterator(d_value.cols), valueBegin, prg(-1, 1));
  63. cv::Mat h_value(d_value);
  64. }
  65. //! [random]
  66. // OpenCV has count non zero, but what if you want to count a specific value?
  67. //! [count_value]
  68. {
  69. cv::cuda::GpuMat d_value(1, 100, CV_32S);
  70. d_value.setTo(cv::Scalar(0));
  71. d_value.colRange(10, 50).setTo(cv::Scalar(15));
  72. auto count = thrust::count(GpuMatBeginItr<int>(d_value), GpuMatEndItr<int>(d_value), 15);
  73. std::cout << count << std::endl;
  74. }
  75. //! [count_value]
  76. // Randomly fill an array then copy only values greater than 0. Perform these tasks on a stream.
  77. //! [copy_greater]
  78. {
  79. cv::cuda::GpuMat d_value(1, 100, CV_32F);
  80. auto valueBegin = GpuMatBeginItr<float>(d_value);
  81. auto valueEnd = GpuMatEndItr<float>(d_value);
  82. cv::cuda::Stream stream;
  83. //! [random_gen_stream]
  84. // Same as the random generation code from before except now the transformation is being performed on a stream
  85. 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));
  86. //! [random_gen_stream]
  87. // Count the number of values we are going to copy
  88. int count = thrust::count_if(thrust::system::cuda::par.on(cv::cuda::StreamAccessor::getStream(stream)), valueBegin, valueEnd, pred_greater<float>(0.0));
  89. // Allocate a destination for copied values
  90. cv::cuda::GpuMat d_valueGreater(1, count, CV_32F);
  91. // Copy values that satisfy the predicate.
  92. thrust::copy_if(thrust::system::cuda::par.on(cv::cuda::StreamAccessor::getStream(stream)), valueBegin, valueEnd, GpuMatBeginItr<float>(d_valueGreater), pred_greater<float>(0.0));
  93. cv::Mat h_greater(d_valueGreater);
  94. }
  95. //! [copy_greater]
  96. return 0;
  97. }