Я читал об оптимизации компилятора по сравнению с оптимизацией ЦП и volatile
по сравнению с барьерами памяти.
Одна вещь, которая мне не ясна, заключается в том, что мое текущее понимание состоит в том, что оптимизация процессора и оптимизация компилятора ортогональны. т.е. могут происходить независимо друг от друга.
Однако в статье volatile считается вредным подчеркивает, что volatile
не следует использовать. В сообщении Линуса содержатся аналогичные утверждения. Основная причина, IIUC, заключается в том, что пометка переменной как volatile
отключает все оптимизации компилятора при доступе к этой переменной (т.е. даже если они не вредны), но все же не обеспечивает защиту от переупорядочения памяти. По сути, главное заключается в том, что с осторожностью следует обращаться не с данными, а с конкретным шаблоном доступа.
Теперь статья volatile считается вредной. дает следующий пример занятого цикла, ожидающего флага:
while (my_variable != what_i_want) {}
и подчеркивает, что компилятор может оптимизировать доступ к my_variable
так, чтобы он выполнялся только один раз, а не в цикле. Решение, как утверждается в статье, следующее:
while (my_variable != what_i_want)
cpu_relax();
Говорят, что cpu_relax
действует как барьер компилятора (в более ранних версиях статьи говорилось, что это барьер памяти).
У меня есть несколько пробелов здесь:
1) Подразумевается ли, что gcc обладает специальными знаниями о вызове cpu_relax
и что он преобразуется в подсказку как компилятору , так и ЦП?
2) То же самое относится и к другим инструкциям, таким как smb_mb()
и им подобным?
3) Как это работает, учитывая, что cpu_relax
по существу определяется как макрос C? Если я вручную расширю cpu_relax
, будет ли gcc по-прежнему уважать его как барьер компилятора? Как я могу узнать, какие вызовы соблюдаются gcc?
4) Какова область действия cpu_relax
в отношении gcc? Другими словами, каков объем операций чтения, которые не может оптимизировать gcc, когда он видит инструкцию cpu_relax
? С точки зрения ЦП область действия широка (барьеры памяти ставят отметку в буфере чтения или записи). Я предполагаю, что gcc использует меньшую область видимости — возможно, область C?