警告 X3557:循环仅执行 0 次迭代,强制循环展开
warning X3557: loop only executes for 0 iteration(s), forcing loop to unroll
编译器生成 "warning X3557: loop only executes for 0 iteration(s), forcing loop to unroll",我不明白为什么。
这是源代码。这是一个重新访问的 itoa() 函数,用于 HLSL 在 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 循环,但这并没有改变任何东西。还尝试使用属性 [fasopt] 但没有成功。据我所知,函数产生了正确的结果。
感谢任何帮助。
您收到的警告是
WAR_TOO_SIMPLE_LOOP 3557 The loop only executes for a limited number
of iterations or doesn't seem to do anything so consider removing it
or forcing it to unroll.
如果您认为循环在 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) == 0
。 I
的最终值在 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
不应该被编译器知道。
您报告的警告
warning X3557: loop only executes for 0 iteration(s), forcing loop to unroll
如果 if ((Num /= Base) == 0)
在第一次迭代时总是计算为 true
,则 可能指的是第一个循环。在这种情况下,I
将等于 1,而 J
在第二个循环中将等于 0。第二个循环不会 运行 因为 K < J
会在第一次迭代时评估为 false
。
如果你让它 [unroll]
最后得到的可能是 while
循环上的一次迭代,并完全删除后续的 for
循环。我高度怀疑这不是您的预期行为,虽然它可能会抑制警告,但您可能想要检查代码并查看是否有某些地方没有 运行 它应该的方式。
编译器生成 "warning X3557: loop only executes for 0 iteration(s), forcing loop to unroll",我不明白为什么。
这是源代码。这是一个重新访问的 itoa() 函数,用于 HLSL 在 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 循环,但这并没有改变任何东西。还尝试使用属性 [fasopt] 但没有成功。据我所知,函数产生了正确的结果。
感谢任何帮助。
您收到的警告是
WAR_TOO_SIMPLE_LOOP 3557 The loop only executes for a limited number of iterations or doesn't seem to do anything so consider removing it or forcing it to unroll.
如果您认为循环在 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) == 0
。 I
的最终值在 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
不应该被编译器知道。
您报告的警告
如果warning X3557: loop only executes for 0 iteration(s), forcing loop to unroll
if ((Num /= Base) == 0)
在第一次迭代时总是计算为 true
,则 可能指的是第一个循环。在这种情况下,I
将等于 1,而 J
在第二个循环中将等于 0。第二个循环不会 运行 因为 K < J
会在第一次迭代时评估为 false
。
如果你让它 [unroll]
最后得到的可能是 while
循环上的一次迭代,并完全删除后续的 for
循环。我高度怀疑这不是您的预期行为,虽然它可能会抑制警告,但您可能想要检查代码并查看是否有某些地方没有 运行 它应该的方式。