-1

如果我有一个内核,它回顾最后的 Xmins 并计算 float[] 中所有值的平均值,如果所有线程没有同时执行同一行代码,我会遇到性能下降吗?

例如:假设@ x=1500,过去 2 小时有 500 个数据点。

@ x = 1510,过去 2 小时有 300 个数据点。

x = 1500 处的线程必须回溯 500 个位置,而 x = 1510 处的线程只回溯 300,因此后面的线程将在第一个线程完成之前移动到下一个位置。

这通常是一个问题吗?

编辑:示例代码。对不起,但它在 C# 中,因为我打算使用 CUDAfy.net。希望它提供了我需要运行的编程结构类型的粗略概念(实际代码更复杂但结构相似)。任何关于这是否适用于 GPU / 协处理器或仅适用于 CPU 的评论将不胜感激。

public void PopulateMeanArray(float[] data)
{
    float lookFwdDistance = 108000000000f;
    float lookBkDistance = 12000000000f;
    int counter = thread.blockIdx.x * 1000;    //Ensures unique position in data is written to (assuming i have less than 1000 entries).
    float numberOfTicksInLookBack = 0;
    float sum = 0;    //Stores the sum of difference between two time ticks during x min look back.

    //Note:Time difference between each time tick is not consistent, therefore different value of numberOfTicksInLookBack at each position.
    //Thread 1 could be working here.
    for (float tickPosition = SDS.tick[thread.blockIdx.x]; SDS.tick[tickPosition] < SDS.tick[(tickPosition + lookFwdDistance)]; tickPosition++)
    {
        sum = 0;
        numberOfTicksInLookBack = 0;

        //Thread 2 could be working here. Is this warp divergence?
        for(float pastPosition = tickPosition - 1; SDS.tick[pastPosition] > (SDS.tick[tickPosition - lookBkDistance]); pastPosition--)
        {
            sum += SDS.tick[pastPosition] - SDS.tick[pastPosition + 1];
            numberOfTicksInLookBack++;
        }
        data[counter] = sum/numberOfTicksInLookBack;
        counter++;
    }
}
4

1 回答 1

2

CUDA 在称为 warp 的组中运行线程。在迄今为止已实现的所有 CUDA 架构上(计算能力最高为 3.5),warp 的大小为 32 个线程。只有不同 warp 中的线程才能真正位于代码中的不同位置。在经线中,线始终位于同一位置。在执行该代码时,任何不应在给定位置执行代码的线程都将被禁用。然后被禁用的线程只是在扭曲中占用空间并导致它们相应的处理周期丢失。

在您的算法中,您会得到扭曲发散,因为内部循环中的退出条件对于扭曲中的所有线程都没有同时满足。GPU 必须继续执行内部循环,直到 warp 中的所有线程都满足退出条件。随着扭曲中的更多线程达到其退出条件,它们被机器禁用并代表丢失的处理周期。

在某些情况下,丢失的处理周期可能不会影响性能,因为禁用的线程不会发出内存请求。如果您的算法受内存限制,并且禁用线程所需的内存未包含在 warp 中的其他线程之一完成的读取中,则会出现这种情况。但是,在您的情况下,数据以合并访问的方式排列(这是一件好事),因此您最终会失去禁用线程的性能。

您的算法非常简单,就目前而言,该算法不太适合 GPU。但是,我认为使用不同的算法可以在 CPU 和 GPU 上显着加快相同的计算速度,该算法使用的方法更像并行缩减中使用的方法。不过,我还没有考虑过如何以具体的方式做到这一点。

为了潜在地显着提高 CPU 的速度,一个简单的尝试是改变你的算法,使内部循环向前迭代而不是向后迭代。这是因为 CPU 会进行缓存预取。这些仅在您向前遍历数据时才有效。

于 2013-06-11T14:39:02.150 回答