opencv 源码分析 CUDA可分离滤波器设计 ( 发现OpenCV的cuda真TM慢 )
1. 主函数
void SeparableLinearFilter::apply(InputArray _src, OutputArray _dst, Stream& _stream)
{
GpuMat src = _src.getGpuMat();
CV_Assert( src.type() == srcType_ ); _dst.create(src.size(), dstType_);
GpuMat dst = _dst.getGpuMat(); ensureSizeIsEnough(src.size(), bufType_, buf_); DeviceInfo devInfo;
const int cc = devInfo.majorVersion() * + devInfo.minorVersion(); cudaStream_t stream = StreamAccessor::getStream(_stream); rowFilter_(src, buf_, rowKernel_.ptr<float>(), rowKernel_.cols, anchor_.x, rowBorderMode_, cc, stream);
columnFilter_(buf_, dst, columnKernel_.ptr<float>(), columnKernel_.cols, anchor_.y, columnBorderMode_, cc, stream);
}
the block of col is 16X16 , the block of row is 32X8
2. COL
namespace filter
{
template <typename T, typename D>
void linearColumn(PtrStepSzb src, PtrStepSzb dst, const float* kernel, int ksize, int anchor, int brd_type, int cc, cudaStream_t stream)
{
typedef void (*caller_t)(PtrStepSz<T> src, PtrStepSz<D> dst, const float* kernel, int anchor, int cc, cudaStream_t stream); static const caller_t callers[][] =
{
{
,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller< , T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>,
column_filter::caller<, T, D, BrdColConstant>
},
{
,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller< , T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>,
column_filter::caller<, T, D, BrdColReplicate>
},
{
,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller< , T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>,
column_filter::caller<, T, D, BrdColReflect>
},
{
,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller< , T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>,
column_filter::caller<, T, D, BrdColWrap>
},
{
,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller< , T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>,
column_filter::caller<, T, D, BrdColReflect101>
}
}; callers[brd_type][ksize]((PtrStepSz<T>)src, (PtrStepSz<D>)dst, kernel, anchor, cc, stream);
}
}
template <int KSIZE, typename T, typename D, template<typename> class B>
void caller(PtrStepSz<T> src, PtrStepSz<D> dst, const float* kernel, int anchor, int cc, cudaStream_t stream)
{
int BLOCK_DIM_X;
int BLOCK_DIM_Y;
int PATCH_PER_BLOCK; if (cc >= )
{
BLOCK_DIM_X = 16;
BLOCK_DIM_Y = 16;
PATCH_PER_BLOCK = 4;
}
else
{
BLOCK_DIM_X = 16;
BLOCK_DIM_Y = 8;
PATCH_PER_BLOCK = 2;
} const dim3 block(BLOCK_DIM_X, BLOCK_DIM_Y);
const dim3 grid(divUp(src.cols, BLOCK_DIM_X), divUp(src.rows, BLOCK_DIM_Y * PATCH_PER_BLOCK)); B<T> brd(src.rows); linearColumnFilter<KSIZE, T, D><<<grid, block, , stream>>>(src, dst, kernel, anchor, brd); cudaSafeCall( cudaGetLastError() ); if (stream == )
cudaSafeCall( cudaDeviceSynchronize() );
}
}
#define MAX_KERNEL_SIZE 32
template <int KSIZE, typename T, typename D, typename B>
__global__ void linearColumnFilter(const PtrStepSz<T> src, PtrStep<D> dst, const float* kernel, const int anchor, const B brd)
{
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 200)
const int BLOCK_DIM_X = ;
const int BLOCK_DIM_Y = ;
const int PATCH_PER_BLOCK = ;
const int HALO_SIZE = KSIZE <= ? : ;
#else
const int BLOCK_DIM_X = ;
const int BLOCK_DIM_Y = ;
const int PATCH_PER_BLOCK = ;
const int HALO_SIZE = ;
#endif
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type sum_t;
__shared__ sum_t smem[(PATCH_PER_BLOCK + * HALO_SIZE) * BLOCK_DIM_Y][BLOCK_DIM_X];
const int x = blockIdx.x * BLOCK_DIM_X + threadIdx.x;
if (x >= src.cols)
return;
const T* src_col = src.ptr() + x;
const int yStart = blockIdx.y * (BLOCK_DIM_Y * PATCH_PER_BLOCK) + threadIdx.y;
if (blockIdx.y > )
{
//Upper halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y + j * BLOCK_DIM_Y][threadIdx.x] = saturate_cast<sum_t>(src(yStart - (HALO_SIZE - j) * BLOCK_DIM_Y, x));
}
else
{
//Upper halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y + j * BLOCK_DIM_Y][threadIdx.x] = saturate_cast<sum_t>(brd.at_low(yStart - (HALO_SIZE - j) * BLOCK_DIM_Y, src_col, src.step));
}
if (blockIdx.y + < gridDim.y)
{
//Main data
#pragma unroll
for (int j = ; j < PATCH_PER_BLOCK; ++j)
smem[threadIdx.y + HALO_SIZE * BLOCK_DIM_Y + j * BLOCK_DIM_Y][threadIdx.x] = saturate_cast<sum_t>(src(yStart + j * BLOCK_DIM_Y, x));
//Lower halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y + (PATCH_PER_BLOCK + HALO_SIZE) * BLOCK_DIM_Y + j * BLOCK_DIM_Y][threadIdx.x] = saturate_cast<sum_t>(src(yStart + (PATCH_PER_BLOCK + j) * BLOCK_DIM_Y, x));
}
else
{
//Main data
#pragma unroll
for (int j = ; j < PATCH_PER_BLOCK; ++j)
smem[threadIdx.y + HALO_SIZE * BLOCK_DIM_Y + j * BLOCK_DIM_Y][threadIdx.x] = saturate_cast<sum_t>(brd.at_high(yStart + j * BLOCK_DIM_Y, src_col, src.step));
//Lower halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y + (PATCH_PER_BLOCK + HALO_SIZE) * BLOCK_DIM_Y + j * BLOCK_DIM_Y][threadIdx.x] = saturate_cast<sum_t>(brd.at_high(yStart + (PATCH_PER_BLOCK + j) * BLOCK_DIM_Y, src_col, src.step));
}
__syncthreads();
#pragma unroll
for (int j = ; j < PATCH_PER_BLOCK; ++j)
{
const int y = yStart + j * BLOCK_DIM_Y;
if (y < src.rows)
{
sum_t sum = VecTraits<sum_t>::all();
#pragma unroll
for (int k = ; k < KSIZE; ++k)
sum = sum + smem[threadIdx.y + HALO_SIZE * BLOCK_DIM_Y + j * BLOCK_DIM_Y - anchor + k][threadIdx.x] * kernel[k];
dst(y, x) = saturate_cast<D>(sum);
}
}
}
3. ROW
namespace filter
{
template <typename T, typename D>
void linearRow(PtrStepSzb src, PtrStepSzb dst, const float* kernel, int ksize, int anchor, int brd_type, int cc, cudaStream_t stream)
{
typedef void (*caller_t)(PtrStepSz<T> src, PtrStepSz<D> dst, const float* kernel, int anchor, int cc, cudaStream_t stream); static const caller_t callers[][] =
{
{
,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller< , T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>,
row_filter::caller<, T, D, BrdRowConstant>
},
{
,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller< , T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>,
row_filter::caller<, T, D, BrdRowReplicate>
},
{
,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller< , T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>,
row_filter::caller<, T, D, BrdRowReflect>
},
{
,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller< , T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>,
row_filter::caller<, T, D, BrdRowWrap>
},
{
,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller< , T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>,
row_filter::caller<, T, D, BrdRowReflect101>
}
}; callers[brd_type][ksize]((PtrStepSz<T>)src, (PtrStepSz<D>)dst, kernel, anchor, cc, stream);
}
}
template <int KSIZE, typename T, typename D, template<typename> class B>
void caller(PtrStepSz<T> src, PtrStepSz<D> dst, const float* kernel, int anchor, int cc, cudaStream_t stream)
{
int BLOCK_DIM_X;
int BLOCK_DIM_Y;
int PATCH_PER_BLOCK; if (cc >= )
{
BLOCK_DIM_X = 32;
BLOCK_DIM_Y = 8;
PATCH_PER_BLOCK = 4;
}
else
{
BLOCK_DIM_X = ;
BLOCK_DIM_Y = ;
PATCH_PER_BLOCK = ;
} const dim3 block(BLOCK_DIM_X, BLOCK_DIM_Y);
const dim3 grid(divUp(src.cols, BLOCK_DIM_X * PATCH_PER_BLOCK), divUp(src.rows, BLOCK_DIM_Y)); B<T> brd(src.cols); linearRowFilter<KSIZE, T, D><<<grid, block, , stream>>>(src, dst, kernel, anchor, brd);
cudaSafeCall( cudaGetLastError() ); if (stream == )
cudaSafeCall( cudaDeviceSynchronize() );
}
#define MAX_KERNEL_SIZE 32
template <int KSIZE, typename T, typename D, typename B>
__global__ void linearRowFilter(const PtrStepSz<T> src, PtrStep<D> dst, const float* kernel, const int anchor, const B brd)
{
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 200)
const int BLOCK_DIM_X = ;
const int BLOCK_DIM_Y = ;
const int PATCH_PER_BLOCK = ;
const int HALO_SIZE = ;
#else
const int BLOCK_DIM_X = ;
const int BLOCK_DIM_Y = ;
const int PATCH_PER_BLOCK = ;
const int HALO_SIZE = ;
#endif
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type sum_t;
__shared__ sum_t smem[BLOCK_DIM_Y][(PATCH_PER_BLOCK + * HALO_SIZE) * BLOCK_DIM_X];
const int y = blockIdx.y * BLOCK_DIM_Y + threadIdx.y;
if (y >= src.rows)
return;
const T* src_row = src.ptr(y);
const int xStart = blockIdx.x * (PATCH_PER_BLOCK * BLOCK_DIM_X) + threadIdx.x;
if (blockIdx.x > )
{
//Load left halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y][threadIdx.x + j * BLOCK_DIM_X] = saturate_cast<sum_t>(src_row[xStart - (HALO_SIZE - j) * BLOCK_DIM_X]);
}
else
{
//Load left halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y][threadIdx.x + j * BLOCK_DIM_X] = saturate_cast<sum_t>(brd.at_low(xStart - (HALO_SIZE - j) * BLOCK_DIM_X, src_row));
}
if (blockIdx.x + < gridDim.x)
{
//Load main data
#pragma unroll
for (int j = ; j < PATCH_PER_BLOCK; ++j)
smem[threadIdx.y][threadIdx.x + HALO_SIZE * BLOCK_DIM_X + j * BLOCK_DIM_X] = saturate_cast<sum_t>(src_row[xStart + j * BLOCK_DIM_X]);
//Load right halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y][threadIdx.x + (PATCH_PER_BLOCK + HALO_SIZE) * BLOCK_DIM_X + j * BLOCK_DIM_X] = saturate_cast<sum_t>(src_row[xStart + (PATCH_PER_BLOCK + j) * BLOCK_DIM_X]);
}
else
{
//Load main data
#pragma unroll
for (int j = ; j < PATCH_PER_BLOCK; ++j)
smem[threadIdx.y][threadIdx.x + HALO_SIZE * BLOCK_DIM_X + j * BLOCK_DIM_X] = saturate_cast<sum_t>(brd.at_high(xStart + j * BLOCK_DIM_X, src_row));
//Load right halo
#pragma unroll
for (int j = ; j < HALO_SIZE; ++j)
smem[threadIdx.y][threadIdx.x + (PATCH_PER_BLOCK + HALO_SIZE) * BLOCK_DIM_X + j * BLOCK_DIM_X] = saturate_cast<sum_t>(brd.at_high(xStart + (PATCH_PER_BLOCK + j) * BLOCK_DIM_X, src_row));
}
__syncthreads();
#pragma unroll
for (int j = ; j < PATCH_PER_BLOCK; ++j)
{
const int x = xStart + j * BLOCK_DIM_X;
if (x < src.cols)
{
sum_t sum = VecTraits<sum_t>::all();
#pragma unroll
for (int k = ; k < KSIZE; ++k)
sum = sum + smem[threadIdx.y][threadIdx.x + HALO_SIZE * BLOCK_DIM_X + j * BLOCK_DIM_X - anchor + k] * kernel[k];
dst(y, x) = saturate_cast<D>(sum);
}
}
}
opencv 源码分析 CUDA可分离滤波器设计 ( 发现OpenCV的cuda真TM慢 )的更多相关文章
- OpenCV源码分析:RGB到其他色彩空间的转换
1.流程调用图 2.部分代码分析 //模板函数进行颜色空间的转换 template <typename Cvt> void CvtColorLoop(const Mat& src, ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- Redis学习——ae事件处理源码分析
0. 前言 Redis在封装事件的处理采用了Reactor模式,添加了定时事件的处理.Redis处理事件是单进程单线程的,而经典Reator模式对事件是串行处理的.即如果有一个事件阻塞过久的话会导致整 ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
- MQTT再学习 -- MQTT 客户端源码分析
MQTT 源码分析,搜索了一下发现网络上讲的很少,多是逍遥子的那几篇. 参看:逍遥子_mosquitto源码分析系列 参看:MQTT libmosquitto源码分析 参看:Mosquitto学习笔记 ...
- Visual Studio调试到OpenCV源码中
TL;DR VS2015下,build-farm/vs2015-x64/bin/Debug/目录,*.pdb文件,都拷贝到install/x64/vc14/bin目录,就可以调试进去opencv源码了 ...
- springmvc拦截器入门及其执行顺序源码分析
springmvc拦截器是偶尔会用到的一个功能,本案例来演示一个较简单的springmvc拦截器的使用,并通过源码来分析拦截器的执行顺序的控制.具体操作步骤为:1.maven项目引入spring依赖2 ...
- druid 源码分析与学习(含详细监控设计思路的彩蛋)(转)
原文路径:http://herman-liu76.iteye.com/blog/2308563 Druid是阿里巴巴公司的数据库连接池工具,昨天突然想学习一下阿里的druid源码,于是下载下来分析了 ...
随机推荐
- 前端VScode推荐插件
Auto Close Tag 自动添加HTML / XML关闭标签 Auto Rename Tag 自动重命名配对的HTML / XML标签 Beautify 格式化代码 [必须]Bracket Pa ...
- Mysql问题1862
使用Navicat连接MySQL数据库出现1862错误(1862:Your password has expired.To log in you must change it change it us ...
- 剑指offer:二叉搜索树与双向链表
题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路分析: 这道题一开始的思路是借用队列结构,首先中序遍历二叉树,按顺序 ...
- SpringBoot使用jasypt加解密密码
在我们的服务中不可避免的需要使用到一些秘钥(数据库.redis等) 开发和测试环境还好,但生产如果采用明文配置讲会有安全问题,jasypt是一个通用的加解密库,我们可以使用它. <depende ...
- python2中的unicode()函数在python3中会报错:
python2中的unicode()函数在python3中会报错:NameError: name 'unicode' is not defined There is no such name in P ...
- java 多线程 面试
1.多线程有什么用? (1)发挥多核CPU的优势: 当前,应用服务器至少也都是双核的,4核.8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75 ...
- maven设置阿里云仓库
到maven安装目录的conf下setting.xml文件 找到mirrors标签中添加 <mirror> <id>nexus-aliyun</id> <mi ...
- 获取apk的Activity和Package
2.查看包名和activity adb logcat|grep -i activitymanager 获取当前界面的activity 1.adb shell dumpsys window window ...
- windows下大数据开发环境搭建(1)——Java环境搭建
一.Java 8下载 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下载之后 ...
- OpenGL入门学习--超级好的资料
近几天,由于工作项目需要利用openGL显示STL格式的三维模型,分享下面的BOOK,这个老外写得真是TMD太好了,资料免费! http://www.glprogramming.com/red/ind ...