繁体   English   中英

控制GCC优化

[英]Controlling GCC optimization

我正在尝试测试我可以访问的计算机的缓存属性。 为此,我尝试读取内存并为其计时。 我更改工作集的大小和跨度访问模式以进行不同的测量。

代码如下所示:

clock1 = get_ticks()
for (i = 0; i < 1000000; i++) {
  for (j = 0; j < (workingset * stride / sizeof(data_t)); j += stride) {
    *array[j];
  }
}
clock2 = get_ticks()

现在的问题是,以合理的优化级别,gcc将优化读取,因为它没有副作用。 我不能没有优化级别,否则所有循环变量都会导致对内存的读取。 我尝试了一些不同的事情,例如使数组变得易变,并使用强制转换为易变的内联函数,但是gcc对易变变量的处理很难预测。 什么是合适的方法?

一种可能是以难以轻易优化的方式使用数组数据,例如

clock1 = get_ticks();
sum = 0;
for (i = 0; i < 1000000; i++) {
  for (j = 0; j < (workingset * stride / sizeof(data_t)); j += stride) {
    sum += array[j];
  }
}
clock2 = get_ticks();
return sum;

sum应该在寄存器中,并且add操作不应对循环时序增加任何重要影响。

如果测试函数和调用者都在同一个编译单元中,则可能还需要确保对返回的总和值进行实际操作,例如,通过printf将其输出。

对于GCC,请尝试为所有索引变量( ij )指定used 属性 ,以避免对它们进行编译器优化(即使启用了全局优化选项):

int i __attribute__((used));
int j __attribute__((used));

clock1 = get_ticks()
for (i = 0; i < 1000000; i++) {
  for (j = 0; j < (workingset * stride / sizeof(data_t)); j += stride) {
    *array[j];
    asm (""); // help to avoid cycle's body elimination
  }
}
clock2 = get_ticks();

还要知道, asm(...)表达式从未得到优化。 您甚至可以在不使用任何汇编程序表达式的情况下使用它,如下所示: asm("");

我想,如果您不希望编译器对其进行模糊处理,则应该真正尝试用汇编器编写它。 您只是不能确保任何“技巧”都将永远有效。 现在可以使用的某些功能可能会在以后的编译器版本中进行优化。 另外,可能很难预测它是否有效。 如果您能够检查汇编代码以查看其是否起作用(即未对其进行优化),那么您也应该能够从头开始编写它?

在每次迭代时将值存储到一个volatile全局变量中。 这将确保发生实际写操作(例如,这是保证在信号处理程序中看到正确值所必需的)。

或者,使用类似

sum += *array[j]^i;

这很容易计算,但要确保编译器无法轻松使用求和公式优化循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM