warpScanInclusive

This commit is contained in:
Vladislav Vinogradov 2012-11-16 12:49:43 +04:00
parent 76e8794e81
commit 572d2d6a84
3 changed files with 99 additions and 2 deletions

View File

@ -54,6 +54,14 @@ namespace cv { namespace gpu { namespace device
return T(); return T();
#endif #endif
} }
__device__ __forceinline__ unsigned int shfl(unsigned int val, int srcLane, int width = warpSize)
{
#if __CUDA_ARCH__ >= 300
return (unsigned int) __shfl((int) val, srcLane, width);
#else
return 0;
#endif
}
__device__ __forceinline__ double shfl(double val, int srcLane, int width = warpSize) __device__ __forceinline__ double shfl(double val, int srcLane, int width = warpSize)
{ {
#if __CUDA_ARCH__ >= 300 #if __CUDA_ARCH__ >= 300
@ -78,6 +86,14 @@ namespace cv { namespace gpu { namespace device
return T(); return T();
#endif #endif
} }
__device__ __forceinline__ unsigned int shfl_down(unsigned int val, unsigned int delta, int width = warpSize)
{
#if __CUDA_ARCH__ >= 300
return (unsigned int) __shfl_down((int) val, delta, width);
#else
return 0;
#endif
}
__device__ __forceinline__ double shfl_down(double val, unsigned int delta, int width = warpSize) __device__ __forceinline__ double shfl_down(double val, unsigned int delta, int width = warpSize)
{ {
#if __CUDA_ARCH__ >= 300 #if __CUDA_ARCH__ >= 300
@ -92,6 +108,38 @@ namespace cv { namespace gpu { namespace device
return 0.0; return 0.0;
#endif #endif
} }
template <typename T>
__device__ __forceinline__ T shfl_up(T val, unsigned int delta, int width = warpSize)
{
#if __CUDA_ARCH__ >= 300
return __shfl_up(val, delta, width);
#else
return T();
#endif
}
__device__ __forceinline__ unsigned int shfl_up(unsigned int val, unsigned int delta, int width = warpSize)
{
#if __CUDA_ARCH__ >= 300
return (unsigned int) __shfl_up((int) val, delta, width);
#else
return 0;
#endif
}
__device__ __forceinline__ double shfl_up(double val, unsigned int delta, int width = warpSize)
{
#if __CUDA_ARCH__ >= 300
int lo = __double2loint(val);
int hi = __double2hiint(val);
lo = __shfl_up(lo, delta, width);
hi = __shfl_up(hi, delta, width);
return __hiloint2double(hi, lo);
#else
return 0.0;
#endif
}
}}} }}}
#endif // __OPENCV_GPU_WARP_SHUFFLE_HPP__ #endif // __OPENCV_GPU_WARP_SHUFFLE_HPP__

View File

@ -65,6 +65,8 @@
#include "NPP_staging/NPP_staging.hpp" #include "NPP_staging/NPP_staging.hpp"
#include "NCVRuntimeTemplates.hpp" #include "NCVRuntimeTemplates.hpp"
#include "NCVHaarObjectDetection.hpp" #include "NCVHaarObjectDetection.hpp"
#include "opencv2/gpu/device/warp.hpp"
#include "opencv2/gpu/device/warp_shuffle.hpp"
//============================================================================== //==============================================================================
@ -81,6 +83,20 @@ NCV_CT_ASSERT(K_WARP_SIZE == 32); //this is required for the manual unroll of th
//assuming size <= WARP_SIZE and size is power of 2 //assuming size <= WARP_SIZE and size is power of 2
__device__ Ncv32u warpScanInclusive(Ncv32u idata, volatile Ncv32u *s_Data) __device__ Ncv32u warpScanInclusive(Ncv32u idata, volatile Ncv32u *s_Data)
{ {
#if __CUDA_ARCH__ >= 300
const unsigned int laneId = cv::gpu::device::Warp::laneId();
// scan on shuffl functions
#pragma unroll
for (int i = 1; i <= (K_WARP_SIZE / 2); i *= 2)
{
const Ncv32u n = cv::gpu::device::shfl_up(idata, i);
if (laneId >= i)
idata += n;
}
return idata;
#else
Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1)); Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1));
s_Data[pos] = 0; s_Data[pos] = 0;
pos += K_WARP_SIZE; pos += K_WARP_SIZE;
@ -93,6 +109,7 @@ __device__ Ncv32u warpScanInclusive(Ncv32u idata, volatile Ncv32u *s_Data)
s_Data[pos] += s_Data[pos - 16]; s_Data[pos] += s_Data[pos - 16];
return s_Data[pos]; return s_Data[pos];
#endif
} }
__device__ __forceinline__ Ncv32u warpScanExclusive(Ncv32u idata, volatile Ncv32u *s_Data) __device__ __forceinline__ Ncv32u warpScanExclusive(Ncv32u idata, volatile Ncv32u *s_Data)

View File

@ -44,6 +44,8 @@
#include <vector> #include <vector>
#include <cuda_runtime.h> #include <cuda_runtime.h>
#include "NPP_staging.hpp" #include "NPP_staging.hpp"
#include "opencv2/gpu/device/warp.hpp"
#include "opencv2/gpu/device/warp_shuffle.hpp"
texture<Ncv8u, 1, cudaReadModeElementType> tex8u; texture<Ncv8u, 1, cudaReadModeElementType> tex8u;
@ -90,6 +92,36 @@ NCV_CT_ASSERT(K_WARP_SIZE == 32); //this is required for the manual unroll of th
//assuming size <= WARP_SIZE and size is power of 2 //assuming size <= WARP_SIZE and size is power of 2
template <class T> template <class T>
inline __device__ T warpScanInclusive(T idata, volatile T *s_Data) inline __device__ T warpScanInclusive(T idata, volatile T *s_Data)
{
#if __CUDA_ARCH__ >= 300
const unsigned int laneId = cv::gpu::device::Warp::laneId();
// scan on shuffl functions
#pragma unroll
for (int i = 1; i <= (K_WARP_SIZE / 2); i *= 2)
{
const T n = cv::gpu::device::shfl_up(idata, i);
if (laneId >= i)
idata += n;
}
return idata;
#else
Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1));
s_Data[pos] = 0;
pos += K_WARP_SIZE;
s_Data[pos] = idata;
s_Data[pos] += s_Data[pos - 1];
s_Data[pos] += s_Data[pos - 2];
s_Data[pos] += s_Data[pos - 4];
s_Data[pos] += s_Data[pos - 8];
s_Data[pos] += s_Data[pos - 16];
return s_Data[pos];
#endif
}
inline __device__ Ncv64u warpScanInclusive(Ncv64u idata, volatile Ncv64u *s_Data)
{ {
Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1)); Ncv32u pos = 2 * threadIdx.x - (threadIdx.x & (K_WARP_SIZE - 1));
s_Data[pos] = 0; s_Data[pos] = 0;