持久线程样式OpenCL实现非常慢

时间:2015-08-05 13:00:12

标签: multithreading opencl

我遇到了非均匀工作分布的持久线程(PT)样式实现,并编写了一个简单的内核来比较计算时间与内核以通常的方式进行相同的计算。但是我的测试实现比普通实现慢大约6倍,即使没有分配缓冲区以获得32的相应操作的开销。这是合理的减速还是我忽略了什么?我使用global_work_size = local_work_size = CL_DEVICE_MAX_WORK_GROUP_SIZE启动了PT内核,这是512.如果我选择的更少,那么显然它会变得更慢。

这是普通的内核:

__kernel void myKernel(const __global int* buffer)
{
    int myIndex = get_local_id(0);
    doSomeComputations(buffer[myIndex]); //just many adds and mults, no conditionals
}

这是PT风格的内核:

__constant int finalIndex = 655360;

__kernel void myKernel(const __global int* buffer)
{
    __local volatile int nextIndex;
    if (get_local_id(0) == 0)
        nextIndex = 0;
    mem_fence(CLK_LOCAL_MEM_FENCE);

    int myIndex;
    while(true){
        // get next index
        myIndex = nextIndex + get_local_id(0);
        if (myIndex > finalIndex)
            return;

        if ( get_local_id(0) == 0)
            nextIndex += 512;
        mem_fence(CLK_LOCAL_MEM_FENCE);

        doSomeComputations(buffer[myIndex]); //same computations as above
    }
}

我认为这两种实现方式应该大致相同。为什么PT风格的实现速度要慢得多?提前谢谢。

------------在此行下编辑-------------

所以要清楚。使用global_work_size = 655360和local_work_size = 512

启动此内核
__kernel void myKernel()
{
    int myIndex = get_local_id(0);
    volatile float result;
    float4 test = float4(1.1f);
    for(int i=0; i<1000; i++)
        test = (test*test + test*test)/2.0;

    result = test.x;
}

运行速度比使用global_work_size = 512和local_work_size = 512启动的内核快6倍

__kernel void myKernel()
{
    for(size_t idx = 0; idx < 655360; idx += get_local_size(0))
    {
        volatile float result;
        float4 test = float4(1.1f);
        for(int i=0; i<1000; i++)
            test = (test*test + test*test)/2.0;

        result = test.x;
    }
}

1 个答案:

答案 0 :(得分:2)

您可以将第二个内核减少到这个:

__kernel void myKernel(const __global int* buffer)
{
    for(int x = 0; x < 655360; x += get_local_size(0))
        doSomeComputations(buffer[x+get_local_id(0)]);
}

更新:添加了以下对话的摘要

第一个内核(global_work_size = 655360和local_work_size = 512)将分为655360/512 = 1280个工作组,这些工作组将充分利用GPU。第二个内核(global_work_size = 512和local_work_size = 512)将只使用一个计算单元,这解释了为什么第一个运行得更快。

有关GPU中持久线程的更多详细信息:persistent-threads-in-opencl-and-cuda