2016-02-18 3 views
0

В CSAPP2e, когда демонстрируя «гора памяти», автор использовал следующий фрагмент кода:Какова цель использования ключевого слова volatile для предотвращения оптимизации в этом фрагменте кода?

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 */ 
} 

Я не совсем понятно, почему мы используем летучими, чтобы избежать оптимизации в тесте() функции. Я видел в wikipedia, что ключевое слово volatile указывает, что значение может меняться между различными обращениями, даже если оно не изменяется, однако я не знаю, почему использовать volatile в этом примере, и если мы не будем использовать volatile , что случится?

+1

Что бы это ни значилось для «горы памяти» (это очень неудобный перевод «кучи»?), Достаточно информации о 'volatile'. И это не предотвращает оптимизацию как таковую. – Olaf

+0

Без назначения нет смысла вычислять * результат *, поэтому нет смысла выполнять цикл, поэтому нет смысла выполнять эту функцию, а тест занимает 0 микросекунд :) –

ответ

3

В соответствии со стандартом C запись в переменную volatile составляет наблюдаемое поведение. (Не имеет большого значения для меня в случае переменной стека, которая не используется впоследствии, но это правила).

Оптимизация компилятора не позволяет изменять наблюдаемое поведение программы, поэтому это вынуждает компилятор выработать значение result, чтобы присвоить его sink.

Если вы не используете volatile, то компилятор может преобразовать всю функцию в no-op, поскольку она не имеет наблюдаемого поведения.

+0

Собственно, компилятор может даже оптимизировать 'volatile' если это может доказать, что поведение не может быть истинно наблюдаемым. автоматический 'volatile', где не может быть указатель на указатель. – Olaf

+0

@Olaf см. Раздел 5.1.2.3/6 C11, запись в изменчивый определяется как наблюдаемое поведение –

+0

Ehm, [5.1.2.3p6] (http://port70.net/~nsz/c/c11/n1570.html # 5.1.2.3p6) просто указывает: «Доступ к изменчивым объектам оценивается строго в соответствии с правилами абстрактной машины». Только модификация, например. 'auto volatile int i;' внутри блока без eg. переход к функциям и без его адреса по-прежнему может быть оптимизирован (возможно, существуют другие недочеты), поскольку компилятор может доказать, что переменная не доступна извне. Я действительно видел такое поведение компилятора, и ** ** соответствует. – Olaf

Смежные вопросы