Как компиляторы С++ поддерживают атомарную С++ 11, но не поддерживают модель памяти С++ 11
При взгляде на статус внедрения Clang и g++ С++ 11 я заметил что-то странное:
они поддерживают атомы С++ 11, но они не поддерживают модель памяти С++ 11.
У меня сложилось впечатление, что у вас должна быть модель памяти С++ 11 для использования атомистики.
Так в чем же разница между поддержкой атомистики и модели памяти?
Недостаток поддержки модели памяти означает, что легальные программы на С++ 11, которые используют std::atomic<T>
arent seq согласованно?
ссылки:
http://clang.llvm.org/cxx_status.html
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html
Ответы
Ответ 1
Одной из проблем является определение "местоположения памяти", которое позволяет (и заставляет компилятор поддерживать) блокировать разные элементы структуры различными блокировками. Существует обсуждение проблемы RL, вызванной этим.
В основном проблема заключается в том, что наличие struct
определяется следующим образом:
struct x {
long a;
unsigned int b1;
unsigned int b2:1;
};
компилятор может свободно записывать на b2
, переписывая b1
тоже (и, судя по отчету, он делает это). Поэтому два поля должны быть заблокированы как одно. Однако, как следствие модели памяти С++ 11, это запрещено (ну, на самом деле, это не запрещено, но компилятор должен обеспечить одновременное обновление b1
и b2
, не вмешиваясь, он может сделать это путем блокировки или CAS-ing каждое такое обновление, ну, на некоторых архитектурах сложно жить). Цитирование из отчета:
Я поднял вопрос с нашими парнями GCC, и они сказали мне, что: "C делает не предоставляют такую гарантию, и вы не можете надежно заблокировать разные структурированные поля с различными замками, если они разделены естественным образом области памяти размера слова. Модель памяти С++ 11 гарантировала бы это, но это не реализовано, и вы не создаете ядро с помощью С++ 11 компилятор".
Приятную информацию можно найти в wiki.
Ответ 2
Я думаю, что "Недостаток модели памяти" в этих случаях просто означает, что оптимизаторы были написаны до публикации модели памяти С++ 11 и могут выполнять теперь недействительные оптимизации. Очень сложно и трудоемко проверять оптимизацию по сравнению с моделью памяти, поэтому не удивительно, что команды clang/gcc еще не закончили это.
Оказывает ли недостаток поддержки модели памяти, что законные программы на С++ 11, которые используют std:: atomic arent seq?
Да, это возможность. Это еще хуже: компилятор может вводить ракеты данных в (в соответствии со стандартами С++ 11) без гонок, например. путем введения спекулятивных записей.
Например, несколько компиляторов С++ использовали эту оптимизацию:
for (p = q; p = p -> next; ++p) {
if (p -> data > 0) ++count;
}
Можно оптимизировать:
register int r1 = count;
for (p = q; p = p -> next; ++p) {
if (p -> data > 0) ++r1;
}
count = r1;
Если все p->data
неотрицательны, исходный код не записывался в count
, но оптимизированный код делает. Это может привести к гонке данных в другой программе без гонок, поэтому спецификация С++ 11 запрещает такую оптимизацию. Существующие компиляторы теперь должны проверять (и при необходимости корректировать) все оптимизации.
Подробнее см. Concurrency последствия компилятора модели памяти.
Ответ 3
Это не так, что они не поддерживают модель памяти, но что они еще не поддерживают API в стандарте для взаимодействия с моделью памяти. Этот API включает в себя несколько мьютексов.
Тем не менее, как Clang, так и GCC были как можно более осведомлены о потоке без формального стандарта в течение некоторого времени. Вам не нужно беспокоиться о том, что оптимизация перемещает объекты в неправильную сторону атомных операций.