第一个数据集的额外执行时间是什么原因?装配说明是相同的。
如果DN_FLUSH标志未打开,则第一个数据集需要63毫秒,第二个数据集需要15毫秒。 在DN_FLUSH标志打开的情况下,第一个数据集需要15毫秒,第二个数据集需要约0毫秒。
因此,在这两种情况下,第一个数据集的执行时间都要大得多。
有没有办法将执行时间缩短到与第二个数据集更接近?
我正在使用C ++ Visual Studio 2005,/ arch:SSE2 / fp:在Intel Core 2 Duo T7700 @ 2.4Ghz Windows XP Pro上快速运行。
#define NUMLOOPS 1000000
// Denormal values flushed to zero by hardware on ALPHA and x86
// processors with SSE2 support. Ignored on other x86 platforms
// Setting this decreases execution time from 63 milliseconds to 16 millisecond
// _controlfp(_DN_FLUSH, _MCW_DN);
float denormal = 1.0e-38;
float denormalTwo = 1.0e-39;
float denormalThree = 1;
tickStart = GetTickCount();
// Run First Calculation Loop
for (loops=0; loops < NUMLOOPS; loops++)
{
denormalThree = denormal - denormalTwo;
}
// Get execution time
duration = GetTickCount()-tickStart;
printf("Duration = %dms\n", duration);
float normal = 1.0e-10;
float normalTwo = 1.0e-2;
float normalThree = 1;
tickStart = GetTickCount();
// Run Second Calculation Loop
for (loops=0; loops < NUMLOOPS; loops++)
{
normalThree = normal - normalTwo;
}
// Get execution time
duration = GetTickCount()-tickStart;
printf("Duration = %dms\n", duration);
答案 0 :(得分:11)
引自英特尔优化手册:
当SIMD的输入操作数时 浮点指令[这里包括使用SSE完成的标量算法]包含 小于的值 可表示的数据类型范围, 发生非正规异常。这个 导致显着的表现 罚款。一个SIMD浮点 操作中有一个清零模式 哪个结果不会下溢。 因此后续计算将 不要面对表现的惩罚 处理非正规输入操作数。
至于如何避免这种情况,如果你不能刷新非规范:尽你所能确保你的数据适当缩放,你首先不会遇到非正规数。通常这意味着延迟应用一些比例因子,直到你完成所有其他计算。
或者,在具有更大指数范围的double
中进行计算,因此首先会遇到非正规数的可能性要小得多。
答案 1 :(得分:2)
英特尔手册第1卷第10.2.3.3章的另一个引用:
从零到零模式与IEEE标准754不兼容.IEM强制要求 对下溢的掩盖响应是提供非规范化结果(参见 第4.8.3.2节“归一化和非规范化有限数”)。冲到零 模式主要是出于性能原因。以微小的精度为代价 对于下溢很常见的应用程序,可以实现丢失,更快的执行 并且可以容忍将下溢结果舍入为零。