如何修改CUDA代码以获得100%的GPU负载

时间:2014-01-08 13:46:50

标签: c++ cuda gpu gpgpu gpu-programming

如何修改此代码以获得100%的GPU负载?

#include <iostream>

using namespace std;

__global__ void saxpy_parallel(int n, float a, float *x, float *y)
{
    // Get the unique ID of this kernel instance
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n)
    {
        y[i] = a*x[i] + y[i];
    }
}

int main(int argc, char const *argv[])
{
    // Tensors length
    int const n = 100;

    // Define tensors
    float x[n], y[n];

    for (int i = 0; i < n; ++i)
    {
        x[i] = 1.0f*i;
        y[i] = 1.0f*i;
    }

    // Device pointers
    float *d_x, *d_y;

    cudaMalloc(&d_x, n*sizeof(float));
    cudaMalloc(&d_y, n*sizeof(float));

    if (cudaMemcpy(d_x, &x, n*sizeof(float), cudaMemcpyHostToDevice) != cudaSuccess)
    {
        printf("Memory Error!\n");
        return 0;
    }

    if (cudaMemcpy(d_y, &y, n*sizeof(float), cudaMemcpyHostToDevice) != cudaSuccess)
    {
        printf("Memory Error!\n");
        return 0;
    }

    // Run the kernel
    saxpy_parallel<<<4096, 512>>>(n, 2.0, d_x, d_y);

    // Retrieve results from the device memory
    cudaMemcpy(&y, d_y, n*sizeof(float), cudaMemcpyDeviceToHost);

    cudaFree(d_y);
    cudaFree(d_x);

    printf("%s\n",y[0]);

    system("PAUSE");
    return 0;
}

1 个答案:

答案 0 :(得分:1)

好吧,让我们忽略100%GPU负载目标,因为它不切实际且不易测量。因此,假设您希望优化此代码以更快地运行。目标是什么?您的算法非常简单,因此它不会带来很多机会。但是,我可以看到以下目标

1)块大小

saxpy_parallel<<<4096, 512>>>

512是最好的数字,我会启动32或64,并在调整内核启动时找到该参数的最佳值时加倍。

2)删除不必要的代码

if( i < n )

如果n总是小于i,则可以删除if语句。这可以在内核外部进行控制。可能需要将奇数大小的数组填充为块大小的倍数,以使其工作。

3)探索矢量类型的使用

CUDA有float2和float4类型。因此,重新编写代码以使用其中任何一个,使用HOPE,通过较少的读取和存储以及并行发生的算术运算,可以更快地访问内存。

4)Unjam the Loop

每个线程当前正在获取一个x,a和y。尝试获取2或4或8个值

...
 y[i] = a*x[i] + y[i];
 y[i+1] = a*x[i+1] + y[i+1];
 y[i+2] = a*x[i+2] + y[i+2];
 y[i+3] = a*x[i+3] + y[i+3];

这需要更少的线程,但每个线程做的更多。尝试使用2,4,6或8进行干扰 值。

5)将结果存储到不同的变量

为结果传递一个额外的参数。然后重新编码

__global__ void saxpy_parallel(int n, float a, float *x, float *y, float * b)

...

  b[i] = a*x[i] + y[i];

这会导致更多内存无法读取和写入同一位置。

不单独尝试每种方法中的每一种,并且在您无法确定哪些方法有效之前和之后测量效果。然后一些组合可能会更好 或者更糟。

尝试一下,玩得开心,让我们知道!