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源码,于是下载下来分析了 ...
随机推荐
- 使用IDEA查看变量调用链
在开发中,我们有时需要查看某个变量是怎么来的,从哪个类的某个方法调用后进入另一个类的某个方法. 如果只有一两层的调用,那么还能直接通过方法跳转来观察. 但是,如果有七八层的调用链呢,在各个方法之间跳来 ...
- hdu4841 圆桌问题[STL vector]
目录 题目地址 题干 代码和解释 参考 题目地址 hdu4841 题干 代码和解释 解本题时使用了刚学的STL vector,注意hdu不支持万能头文件#include<bits/stdc++. ...
- 剑指offer:二叉搜索树与双向链表
题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路分析: 这道题一开始的思路是借用队列结构,首先中序遍历二叉树,按顺序 ...
- ActionFilter、IAuthorizationFilter 权限验证重定向跳转到其它页面
方法一: public class IsAllowAttribute: ActionFilterAttribute { public override void OnActionExecuting(A ...
- GWAS Catalog数据库简介
GWAS Catalog The NHGRI-EBI Catalog of published genome-wide association studies EBI负责维护的一个收集已发表的GWAS ...
- Authenticator App 两步验证会不会造成亚马逊账号关联?
今天听人说,因为用Authenticator App做亚马逊两步验证造成了帐号关联…… 我给大家解释一下Authenticator的实现原理,作为计算机专业科班出身的我,此次从各方面了解并经过自己亲测 ...
- java8之Spliterator
基本用法: import java.util.Arrays; import java.util.Spliterator; import java.util.stream.IntStream; publ ...
- go-micro框架学习1-准备工作
下载golang环境,地址:https://studygolang.com/dl,这里使用的是1.11.10版本. 下载golang IDE,这里使用Lite,下载地址:http://liteide. ...
- sqlserver表被锁了,解锁方法,删除锁的方法
-- 查询死锁select request_session_id spid, OBJECT_NAME(resource_associated_entity_id) table ...
- Qt请求http地址数据
QNetworkAccessManager *manager = new QNetworkAccessManager(this);; QNetworkRequest network_request; ...