OpenCL的GFLOPS非常低,没有数据传输瓶颈

时间:2014-03-14 17:24:37

标签: performance opencl gpgpu

我正在尝试优化我在GPU(AMD HD6850)上运行的算法。我计算了内核中浮点运算的数量并测量了它的执行时间。我发现它可以实现~20 SP GFLOPS,但是根据GPU的规格我应该达到~1500 GFLOPS。

为了找到瓶颈,我创建了一个非常简单的内核:

kernel void test_gflops(const float d, global float* result)
{
    int gid = get_global_id(0);
    float cd;

    for (int i=0; i<100000; i++)
    {
        cd = d*i;
    }

    if (cd == -1.0f)
    {
        result[gid] = cd;
    }
}

运行这个内核我得到~5 * 10 ^ 5 work_items / sec。我计算一个浮点运算(不确定是否正确,如何递增i并将其与100000进行比较?)每次迭代循环。

==&GT; 5 * 10 ^ 5 work_items / sec * 10 ^ 5 FLOPS = 50 GFLOPS。

即使循环中有3个或4个操作,它也比卡应该做的慢得多。我做错了什么?

全球工作规模足够大(10k对100k工作项没有速度变化)。

1 个答案:

答案 0 :(得分:1)

以下是一些技巧:

  1. GPU根本不喜欢循环。使用#pragma展开来展开它们。
  2. 你的GPU擅长矢量操作。坚持下去,这将允许你一次处理多个操作数。
  3. 使用矢量加载/存储是否可行。
  4. 测量内存带宽 - 由于访问模式不佳,我几乎可以确定您的带宽有限。
  5. 在我看来,内核应该是这样的:

    typedef union floats{
        float16 vector;
        float array[16];
    } floats;
    
    kernel void test_gflops(const float d, global float* result)
    {
        int gid = get_global_id(0);
        floats cd;
        cd.vector = vload16(gid, result);
        cd.vector *= d;
    
        #pragma unroll
        for (int i=0; i<16; i++)
        {
            if(cd.array[i] == -1.0f){
            result[gid] = cd;
        }
    }
    

    让你的NDRange更大,以弥补16和16之间的差异。 1000循环条件。