对我的OpenCL内核(DSP窗口函数)的分析结果感到困惑

时间:2010-11-09 19:18:09

标签: profiling cuda signal-processing opencl nvidia

我在OpenCL中完成了一个Window Function内核。基本上,窗口函数只是将一组系数分别应用于另一组数字(维基百科更好地解释了它)。在大多数情况下,我能够将窗口系数浮点数填充到常量缓存中。

我期望Compute Prof的结果表明,托管内存传输的设备和设备的主机将占用超过95%的处理时间。对于我的几乎所有情况,它只占处理时间的80%。我正在编写和读取一个420万个浮动数组进出电路板并编写另一个浮点数组,通常保持在一百万以下。

内核中的任何内容看起来都很可疑吗?关于它是否应该在GPU上比在CPU上运行得更快的问题的任何意见(我仍然不是100%)。我有点惊讶于为什么我的gld_efficiency和gst_efficiency悬停在0.1和0.2之间。我在考虑G80全局内存的情况下制作了这个内核。我的全局内存整体吞吐量似乎还不错,只有40gbs。内核非常简单,发布在下面。

__kernel void window(__global float* inputArray, // first frame to ingest starts at 0.  Sized to nFramesToIngest*framesize samples
    __constant float* windowArray, // may already be partly filled
    int windowSize, // size of window frame, in floats
    int primitivesPerDataFrame, //amount of primitives in each frame of inputArray parameter
    int nInFramesThisCall, //each thread solves a frame, so this integer represent how many threads this kernel launches
    int isRealNumbers //0 for complex, non-zero for real 
)
{
int gid = get_global_id(0) + get_global_size(0) * get_global_id(1);

if(gid < nInFramesThisCall) //make sure we don't execute unnecessary threads
{
    if(isRealNumbers)
    {
        for(int i = 0; i < primitivesPerDataFrame; i++)
        {
            int inputArrayIndex = (gid*primitivesPerDataFrame)+i;
            inputArray[inputArrayIndex] = inputArray[inputArrayIndex] * windowArray[i%windowSize];
        }
    }
    else //complex
    {
        for(int i = 0; i < primitivesPerDataFrame; i++)
        {
            int inputArrayIndex = (gid*primitivesPerDataFrame)+i;
            inputArray[inputArrayIndex] = inputArray[inputArrayIndex] * windowArray[i%windowSize/2];
        }
    }
}

}

1 个答案:

答案 0 :(得分:1)

你使用了多少个线程(OpenCL术语是工作项)?至少需要几百个才能有效地加载大型GPU。

你说你想要使用合并的内存访问,但是使用像

这样的偏移量
int inputArrayIndex = (gid*primitivesPerDataFrame)+i;
在大多数情况下,

不会使这成为可能。 NVidia的G80在合并时有相当严格的限制,有关详细信息,请参阅“OpenCL最佳实践指南”。基本上,来自一个warp的工作项必须同时以某种方式访问​​64或128字节对齐块的元素,以使加载和存储发生合并。

或者举个例子:如果primitivesPerDataFrame为16,则扭曲的加载和存储是在间隔16个元素的偏移处完成的,这使得任何有效的合并都不可能。