2

我正在使用模拟处理器的 pin 工具并遇到一个非常奇怪的问题。在下面的代码片段中,Router::Evaluate() 被多次重复调用。在它被调用数百万次后,会间歇性地发生奇怪的行为,其中“_cycles!= 0”在第一个 IF 语句中被评估为真,而在紧随其后的 IF 语句中被评估为假,落入 ELSE 块。

void Router::Evaluate( )
{     
  //---------debug print code---------
  if (_cycles != 0) {
    cout << "not a zero" << endl;

    if (_cycles != 0) cout << "---not a zero" << endl;
    else cout << "---zero" << endl;

  }        
  //----------------------------------

  _cycles += _speedup;
  while ( _cycles >= 1.0 ) {
    _Step();
    _cycles -= 1.0;
  }
}

//class definition
class Router : public TimedModule {
  Protected:
    double _speedup;  //initialized to 1.0
    double _cycles;  //initialized to 0.0
  ...
}

下面是代码的输出,其中“not a zero”后跟“---zero”不时被打印出来,看似随机。

not a zero
---zero
(...some other output...)
not a zero
---zero
(...some other output...)

这怎么可能发生?这不是一个多线程程序,所以同步不是问题。该程序使用 gcc4.2.4 编译并在 32 位 CentOS 上执行。有人有线索吗?谢谢。

- 添加 - -

我也应该提到这一点。我确实尝试每次打印_cycles的值,它总是0.0,这应该是不可能的......我还使用了以下g ++选项:“-MM -MG -march=i686 -g -ggdb -g1 -finline -功能 -O3 -fPIC"

4

1 回答 1

1

除非你有一个可怕的编译器错误,否则我猜会发生这样的事情:

_cycles 在减法之后还剩下一小部分。只要编译器知道没有其他东西在改变它的内容,它就会把它的值保存在一个更高精度的浮点寄存器中。当它看到 I/O 操作时,不确定其他地方是否需要 _cycles 的值,因此它确保将其内容存储回双精度内存位置,四舍五入寄存器中的额外位。下一个检查悲观地假设该值可能在 I/O 操作期间发生了变化,并将其从内存中加载回来,现在没有在前一个测试中使其非零的额外位。

正如 Daniel Fischer 在评论中提到的,使用-ffloat-store禁止使用高精度寄存器。如果使用此选项时问题消失,那么我描述的情况很可能。检查汇编输出Router::Evaluate以确保。

于 2012-08-06T18:45:18.370 回答