Почему этот временный доступ может быть переупорядочен по отношению к энергонезависимому доступу?

Приведенный ниже пример кода взят из китайского блога, в котором представлен эффект volatile. Левая сторона — это код C; другой - сгенерированный ассемблерный код.

// cordering.c                                gcc -O2 -S -masm=intel cordering.c

int A;
volatile int B;
void foo()                                    mov   eax, DWORD PTR B[rip]
{                                             mov   DWORD PTR B[rip], 0
    A = B + 1;                                add   eax, 1
    B = 0;                                    mov   DWORD PTR A[rip], eax
}                                             ret

Как видно из ассемблерного кода, побочный эффект A размещается после побочного эффекта B, хотя B имеет квалификацию volatile. Однако cppreference.com говорит:

[В] рамках одного потока выполнения изменчивый доступ нельзя оптимизировать или переупорядочить с другим видимым побочным эффектом, который упорядочивается до или после изменчивого доступа.

Здесь побочный эффект A расположен перед B, поэтому я думаю, что компилятор не может это сделать. Я прав?


В качестве дополнения в блоге говорится, что если мы хотим гарантировать последовательность между типами volatile и non-volatile, нам нужно сделать оба типа volatile:

// cordering.c                                gcc -O2 -S -masm=intel cordering.c

volatile int A;
volatile int B;
void foo()                                    mov   eax, DWORD PTR B[rip]
{                                             add   eax, 1
    A = B + 1;                                mov   DWORD PTR A[rip], eax
    B = 0;                                    mov   DWORD PTR B[rip], 0
}                                             ret

person scottxiao    schedule 14.04.2018    source источник
comment
@Constructor   -  person scottxiao    schedule 14.04.2018
comment
@bigxiao markdown很好用的(滑稽),然后汇编的话,在行尾注释吧   -  person John Ding    schedule 14.04.2018
comment
Это сайт только на английском языке, пожалуйста, не используйте другие языки. И вы должны отредактировать свой вопрос, чтобы исправить проблемы   -  person Passer By    schedule 14.04.2018
comment
Код очень похож на код C. Возможно, это не лучший пример, если вы спросите об угловых случаях C++? Я бы держался подальше от любого сайта, пытающегося обучать несуществующему языку C/C++.   -  person Bo Persson    schedule 14.04.2018
comment
+1 за редактирование вопроса и использование английского языка. Вы также можете предоставить живой пример. @BoPersson Я также очень разочарован количеством людей / сайтов, которые считают, что C / C ++ - это вещь.   -  person gflegar    schedule 14.04.2018
comment
Еще одно интересное наблюдение заключается в том, что ни icc, ни clang не выполняют это переупорядочение, похоже, это специфично для gcc.   -  person gflegar    schedule 14.04.2018
comment
@PasserBy Он сказал, что, если он не использует изображение, он думает, что эффект выравнивания не может быть показан идеально.   -  person John Ding    schedule 14.04.2018
comment
@Constructor Одна из причин, по которой вы должны использовать английский язык, и я считаю, что ссылка PasserBy прекрасно объясняет, в чем проблемы с изображениями. Я не думаю, что выравнивание так уж важно, и код всегда можно дополнить ссылкой на godbolt, чтобы получить еще лучшее выравнивание.   -  person gflegar    schedule 14.04.2018
comment
@GoranFlegar Да, ты прав. Чтобы опубликовать качественный вопрос, нужно сделать, как вы говорите. И я просто очень удивлен, что нашел китайский язык на этом сайте, поэтому я использовал китайский язык, извините, я больше не буду этого делать.   -  person John Ding    schedule 14.04.2018


Ответы (1)


На странице, на которую вы ссылаетесь, написано:

Каждый доступ (операция чтения или записи, вызов функции-члена и т. д.), выполненный с помощью выражения glvalue типа volatile-qualified, рассматривается как видимый побочный эффект в целях оптимизации (т. е. в пределах один поток выполнения, изменчивый доступ не может быть оптимизирован или переупорядочен с другим видимым побочным эффектом, который упорядочен до или после изменчивого доступа.

Таким образом, если A не является volatile, доступ к A не рассматривается как видимый побочный эффект, и второе утверждение не применяется (так как оно ничего не говорит о переупорядочении видимых и невидимых доступов).

РЕДАКТИРОВАТЬ: обратите внимание, что cppreference не является официальной документацией для C++, а усилиями сообщества. Я действительно считаю, что цель утверждения, выделенного жирным шрифтом, состояла в том, чтобы определить, что такое видимый побочный эффект, но это написано нечетко.

Окончательной ссылкой является стандарт C++ (здесь приведены некоторые варианты его получения). Проект стандарта N4659 определяет побочные эффекты в [intro.execution], параграф 14, и видимые побочные эффекты в двухстраничной цепочке определений в [intro.races]. Я не эксперт по стандарту C++, поэтому я не могу расшифровать, что именно говорит стандарт без значительных усилий, но вы можете попробовать.

Однако для неформального объяснения того, какие оптимизации разрешено делать компилятору, вы можете взглянуть на правило "как если бы" на cppreference.

РЕДАКТИРОВАТЬ 2: стандарт также формально определяет правило как если бы в [intro.execution], параграф 7:

Минимальные требования к соответствующей реализации:
(7.1) — Доступ через volatile glvalues ​​оценивается строго в соответствии с правилами абстрактной машины.
(7.2) — При завершении программы все данные, записанные в файлы, должны быть идентичен одному из возможных результатов, которые были бы получены при выполнении программы в соответствии с абстрактной семантикой.
(7.3) — Динамика ввода и вывода интерактивных устройств должна иметь место таким образом, чтобы вывод с подсказкой фактически доставлялся до того, как программа ожидает ввода. То, что представляет собой интерактивное устройство, определяется реализацией.

Короче говоря, любая оптимизация действительна, пока программа выдает один и тот же результат, а чтение и запись в volatile-объекты происходят в правильном порядке, который справедлив для исходного примера.

person gflegar    schedule 14.04.2018
comment
Что здесь означает видимый? Меня это смущает. Видимый для кого? - person scottxiao; 14.04.2018
comment
Это то, что выделенное жирным шрифтом утверждение говорит вам, что видимый побочный эффект = доступ осуществляется через выражение типа volatile-qualified, поэтому выражение A не является volatile-квалифицированным и невидимым, а B есть, поэтому оно видимо. - person gflegar; 14.04.2018
comment
Итак, видимый — это просто буквальное определение, не имеющее других понятных значений? - person scottxiao; 14.04.2018
comment
Я так понимаю, однако cppreference не является официальным документом и может содержать ошибки. Смотрите обновленный ответ. - person gflegar; 14.04.2018
comment
Попытка перевести на простой английский: видимый побочный эффект просто означает, что это был последний побочный эффект для изменения этого конкретного объекта. Если модификация еще не произошла, она не видна. Если более поздняя модификация того же объекта уже имела место, более ранняя модификация больше не видна. - person ; 15.04.2018
comment
@hvd, а как вы определяете последний (и позже, и раньше)? Я считаю, что это также то, что стандарт пытается определить, поскольку неясно, что это означает в многопоточной настройке. Означает ли это по настенным часам, т. е. реальное время, когда что-то произошло, или это по какому-то частичному порядку? - person gflegar; 15.04.2018
comment
@GoranFlegar Последнее. Очень короткая история того, что он говорит, заключается в том, что volatile не означает, что вы можете избежать синхронизации между потоками, вам все равно нужно это, чтобы сделать видимыми побочные эффекты. Я не уверен, как перевести это на простой английский более подробно. - person ; 15.04.2018
comment
@hvd спасибо, я верю вам, это нелегко объяснить (иначе им не понадобилось бы 2 страницы в стандарте для этого). Для простых смертных (которые не хотят писать свой собственный компилятор) я бы сказал, что правила «как если бы» достаточно, чтобы рассуждать о программах :) - person gflegar; 15.04.2018