在CSAPP2e中,当演示“内存山”时,作者使用了以下代码:
double data[MAXELEMS]
/* $begin mountainfuns */
void test(int elems, int stride) /* The test function */
{
int i, result = 0;
volatile int sink;
for (i = 0; i < elems; i += stride)
result += data[i];
sink = result; /* So compiler doesn't optimize away the loop */
}
/* Run test(elems, stride) and return read throughput (MB/s) */
double run(int size, int stride, double Mhz)
{
double cycles;
int elems = size / sizeof(int);
test(elems, stride); /* warm up the cache */
cycles = fcyc2(test, elems, stride, 0); /* call test(elems,stride) */
return (size / stride) / (cycles / Mhz); /* convert cycles to MB/s */
}
我不太清楚为什么在函数test()中使用volatile来避免优化。我在维基百科上看到volatile关键字表示一个值可能在不同的访问之间发生变化,即使它看起来没有被修改,但是,我不清楚在这个例子中使用volatile的原因,如果我们不使用volatile,会发生什么?
最佳答案
根据C标准,写入volatile
变量是可观察的行为。(对我来说,在堆栈变量之后不使用的情况下没有太多意义,但它们是规则)。
编译器优化不允许改变程序的可观察行为,因此这会迫使编译器计算出result
的值,以便将其分配给sink
。
如果不使用volatile
编译器可能会将整个函数转换为no op,因为它没有可观察的行为。