警告X3557:循环仅执行0次迭代,迫使循环展开

时间:2019-09-03 07:09:01

标签: directx hlsl directcompute

编译器生成“警告X3557:循环仅执行0次迭代,迫使循环展开”,我不明白为什么。

这是源代码。这是用于HLSL的itoa()函数的重新访问功能,它可以在uint数组中生成结果的ascii代码。

#define ITOA_BUFFER_SIZE 16
// Convert uint to ascii and return number of characters
uint UIntToAscii(
    in  uint Num,                   // Number to convert
    out uint Buf[ITOA_BUFFER_SIZE], // Where to put resulting ascii codes
    in  uint Base)                  // Numeration base for convertion
{
    uint I, J, K;

    I = 0;
    while (I < (ITOA_BUFFER_SIZE - 1)) {   // <==== Warning X3557
        uint Digit = Num % Base;
        if (Digit < 10)
            Buf[I++] = '0' + Digit;
        else
            Buf[I++] = 'A' + Digit - 10;
        if ((Num /= Base) == 0)
            break;
    }

    // Reverse buffer
    for (K = 0, J = I - 1; K < J; K++, J--) {     // <==== Warning X3557
        uint T = Buf[K];
        Buf[K] = Buf[J];
        Buf[J] = T;
    }

    // Fill remaining of buffer with zeros to make compiler happy
    K = I;
    while (K < ITOA_BUFFER_SIZE)
        Buf[K++] = 0;

    return I;
}

我试图重写while循环,但这没有任何改变。也尝试使用属性[fastopt]失败。据我所知,该函数会产生正确的结果。

任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

您收到的警告是

  

WAR_TOO_SIMPLE_LOOP 3557循环仅执行有限的次数   迭代或似乎什么都没做,因此请考虑将其删除   或强迫它展开。

如果您认为循环在GPGPU中被认为效率低下,那么警告几乎是不言自明的,因此编译器会在可能的情况下尝试展开循环。编译器告诉您的是,您创建了一些循环,这些循环在展开时可以更有效地运行,或者可以删除,因为它们永远不会运行。如果循环是不可展开的,则意味着您可以在编译时预测其运行的次数。您乍看之下的循环不符合该标准。

    I = 0;
    while (I < (ITOA_BUFFER_SIZE - 1)) {   // <==== Warning X3557
        uint Digit = Num % Base;
        if (Digit < 10)
            Buf[I++] = '0' + Digit;
        else
            Buf[I++] = 'A' + Digit - 10;
        if ((Num /= Base) == 0)
            break;
    }

此while循环最多运行15次I < (ITOA_BUFFER_SIZE - 1),具体取决于(Num /= Base) == 0I的最终值在1到15之间,这取决于if ((Num /= Base) == 0)在每个周期的评估方式。尽管如此,它仍然是不可展开的,因为编译器可能仍会在迭代中插入条件跳转。

// Reverse buffer
for (K = 0, J = I - 1; K < J; K++, J--) {     // <==== Warning X3557
    uint T = Buf[K];
    Buf[K] = Buf[J];
    Buf[J] = T;
}

第二个循环应该不可展开,因为编译器不应该知道I。 您报告的警告

  

警告X3557:循环仅执行0次迭代,强制循环展开

如果在第一次迭代中if ((Num /= Base) == 0)总是求值为true,则

可能引用第一个循环。在这种情况下,在第二个循环中,I等于1,J等于0。第二个循环不会运行,因为K < J在第一次迭代时的评估结果为false。 如果让它[unroll]最终得到的结果可能是while循环的一次迭代,以及随后的for循环的完全去除。我高度怀疑这不是您的预期行为,尽管它可能会抑制警告,但您可能希望检查代码,看看是否有某些方式无法正常运行。