【问题标题】:Floating Point Math Execution Time浮点数学执行时间
【发布时间】:2010-01-12 18:56:27
【问题描述】:

第一个数据集执行时间增加的原因是什么?组装说明是相同的。

DN_FLUSH 标志未打开时,第一个数据集需要 63 毫秒,第二个数据集需要 15 毫秒。
开启 DN_FLUSH 标志后,第一个数据集需要 15 毫秒,第二个数据集需要 ~0 毫秒。

因此,在这两种情况下,第一个数据集的执行时间要长得多。

有没有什么办法可以减少执行时间以更接近第二个数据集?

我正在使用 C++ Visual Studio 2005,/arch:SSE2 /fp:fast 在 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);

【问题讨论】:

  • 您应该知道 GetTickCount() 对于计时代码几乎毫无价值。它的粒度往往非常大,可能高达 100 毫秒,因系统而异。请改用 QueryPerformanceCounter()。
  • QueryPerformanceCounter() 使用起来很痛苦……试试 timeGetTime()。此外,GetTickCount() 对于运行几秒钟或更长时间的事情并没有那么糟糕 - 请注意准确性。
  • 顺便说一句,不要假设使用 /arch:SSE2 /fp:fast 实际上会使您的代码更快。对于我的代码,我发现 /fp:precise 和使用 FP 堆栈实际上更快。同样,不要假设浮点数比双精度数更快。测试所有选项。

标签: c++ floating-point x86


【解决方案1】:

引用英特尔的优化手册:

当 SIMD 的输入操作数 浮点指令 [这里包括使用 SSE 完成的标量算术] 包含 小于的值 数据类型的可表示范围, 发生异常异常。这 导致显着的性能 惩罚。 SIMD 浮点数 操作有一个清零模式 结果不会下溢。 因此后续计算将 不会面临性能损失 处理非正规输入操作数。

至于如何避免这种情况,如果您无法刷新非正规:尽您所能确保您的数据得到适当的缩放,并且您一开始就不会遇到非正规。通常这意味着延迟应用一些比例因子,直到您完成所有其他计算。

或者,在double 中进行计算,它具有更大的指数范围,因此您一开始就不太可能遇到非规范化。

【讨论】:

  • 顺便说一下,float 的非正规限制大约是 1.18e-38,double 大约是 2.225e-308。
  • @KennyTM:使用基数 2 并避免近似值:在 2**-126 处浮动下溢,在 2**-1022 处加倍
【解决方案2】:

英特尔手册第 1 卷第 10.2.3.3 章的另一句话:

清零模式与 IEEE 标准 754 不兼容。IEEE 规定 对下溢的掩蔽响应是提供非规范化结果(参见 第 4.8.3.2 节,“归一化和非归一化有限数”)。清零 提供模式主要是出于性能原因。以轻微的精度为代价 损失,对于常见下溢的应用程序可以实现更快的执行 并且可以容忍将下溢结果四舍五入为零。

【讨论】:

    猜你喜欢
    • 2010-10-12
    • 1970-01-01
    • 2022-10-02
    相关资源
    最近更新 更多