从cuda性能可以期待什么

时间:2017-01-31 09:31:35

标签: c++ opencv cuda

我最近用cuda编写了一些简单的代码但是虽然我听说它可以加快速度但我看不到多少。 例如,我用cuda编写了2个代码(不使用任何库,如NPP和......)。

首先是模糊过滤器(没有纹理记忆)。

第二个基于模糊的分割(包括一些每个元素的乘法,加法,除法和一些求和,我使用了点积的样本代码和一些模糊滤波器)。

但在第一种情况下我的代码有点慢!!!比类似的OpenCV代码和第二个代码只给我加速了2倍。

我的系统(英特尔酷睿i7 4700HQ 2.4GHz和Geforce GT 750m)(N46JV华硕笔记本电脑) 我在Windows 10中使用Visual Studio 2015,Cuda 8,OpenCV 3.1。

我的代码给了我结果,逻辑上是正确的。

我的问题是我应该从我的系统中获得更多信息吗?

我也使用了一些NPP代码,但它没有改变任何东西,甚至比我自己的代码慢一点(减少)

之前我问了一些人,这是我最后的希望!

例如求和代码:

__global__ void GF3_kernel(double* oldU_temp,
int width,
int height,
double* d_partial_sum_t) {
__shared__ double L[nthreadsGF3];

//Initialize shared memory:
L[threadIdx.x] = 0;
__syncthreads();


//calculate pixel coordinates
const int tid_in = blockIdx.x * blockDim.x + threadIdx.x;
int tid_test = tid_in;

const int cacheXIndex = threadIdx.x;

//temperory sum
double temp = 0;


tid_test = tid_in;
//power random pixels of thread
while (tid_test < width * height) {
    temp += oldU_temp[tid_test];
    tid_test += gridDim.x * blockDim.x;
}
L[cacheXIndex] = temp;
__syncthreads();

int p_idx = blockDim.x / 2;
while (p_idx != 0) {
    if (cacheXIndex < p_idx) {
        L[cacheXIndex] += L[cacheXIndex + p_idx];
    }
    __syncthreads();
    p_idx /= 2;
}
if (cacheXIndex == 0) {
    d_partial_sum_t[blockIdx.x] = L[0];
}
}

并且内核调用将是:

    /////////////////////////////////////////////////////////// sum /////////////////////////////////////////////////////////////

    GF3_kernel << <gridGF3, nthreadsGF3 >> >(d_oldU_temp, width, height, d_partial_sum_t);


    // copy for final summation in cpu
    cudaDeviceSynchronize();
    cudaMemcpy(partial_sum_t, d_partial_sum_t, gridGF3 * sizeof(double),     cudaMemcpyDeviceToHost);
    cudaDeviceSynchronize();
    //Summation result
    sum_temp = 0;
    //calculate Summation
    for (int j = 0; j < gridGF3; j++) {
        sum_temp += partial_sum_t[j];
    }
这样的事情。

你觉得怎么样?

图像是尺寸为390x390像素的1通道图像

1 个答案:

答案 0 :(得分:0)

你不能指望GPGPU computig的奇迹。如果比较高端cpus和gpus的浮点峰值性能,则根据精度得到4到10左右的系数。 如果你设法以一种有效的方式使用你的CPU,你可以期望你可以实现这个加速,如果你可以充分利用gpu。这很安静。首先,并非所有问题都适用于大规模并行GPU架构,第二个优化GPU代码很难。

如果您想尝试从gpu中获得更多性能,请尝试优化内存访问。这就是你将失去大部分表现的地方。 全局内存中的未对齐访问和随机访问将使您的性能降低90%以上。尝试将数据对齐并将其缓存在共享内存中。这将带给你很长的路要走。 另一个技巧是使内核使用更少的寄存器。一般来说,每个线程使用的寄存器越少,就可以在一个流式多处理器上同时调度。

__global__ void GF3_kernel(
double* oldU_temp,
int width,
int height,
double* d_partial_sum_t) {
__shared__ double L[nthreadsGF3];

//Initialize shared memory:
L[threadIdx.x] = 0;
__syncthreads(); //__syncthreads does hurt performance. Use it if absolutly needed


//calculate pixel coordinates

//const int tid_in = blockIdx.x * blockDim.x + threadIdx.x; //not needed
int tid_test = blockIdx.x * blockDim.x + threadIdx.x;

//const int cacheXIndex = threadIdx.x; // not needed

//temperory sum
double temp = 0;


//tid_test = tid_in; //unneeded assignment
//power random pixels of thread
const int endRange = width * height; //most likely done by compiler, but just in case its not.
const int step = gridDim.x * blockDim.x; //same here
while (tid_test < endRange) {
    temp += oldU_temp[tid_test]; // aligned access in global memory is fine
    tid_test += step;
}
L[cacheXIndex] = temp;
__syncthreads();


// This looks like an reduction to me
// Looks fine but there is some potential
// https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwik5IO7nOzRAhWDDRoKHVUuC0kQFggcMAA&url=http%3A%2F%2Fdeveloper.download.nvidia.com%2Fcompute%2Fcuda%2F1.1-Beta%2Fx86_website%2Fprojects%2Freduction%2Fdoc%2Freduction.pdf&usg=AFQjCNFZmgdihbG17glvRmF-zPHfmUR4Aw&sig2=Yil-X_Byf6T6_dKAtN80Aw
int p_idx = blockDim.x / 2;
while (p_idx != 0) {
    if (cacheXIndex < p_idx) {
        L[cacheXIndex] += L[cacheXIndex + p_idx];
    }
    __syncthreads();
    p_idx /= 2;
}
if (cacheXIndex == 0) {
    d_partial_sum_t[blockIdx.x] = L[0];
}
}