#c #multithreading #cpu #atomic
#c #многопоточность #процессор #атомарная
Вопрос:
В моем понимании атомарная операция (например, c atomic) сначала блокирует строку кэша, а затем выполняет атомарную операцию. У меня есть два вопроса: 1. если, допустим, атомарное сравнение и замена — это сама атомарная операция в аппаратном обеспечении, почему нам нужно блокировать строку кэша и 2. когда строка кэша заблокирована, как ее ожидает другой процессор? использует ли он ожидание в стиле спин-блокировки?
Спасибо
Комментарии:
1. Вы читали это: fgiesen.wordpress.com/2014/08/18/atomics-and-contention
2. При наличии нескольких ядер атомарное изменение должно вступить в силу для каждого ядра. Поскольку другое ядро, возможно, кэшировало то же хранилище, оно должно аннулировать хранилище, чтобы гарантировать, что оно «увидит» изменение. ИМХО, это обычная проблема, как подробно это делается. Я не уверен, подходит ли C для этого (за исключением того, что он предоставляет
std::atomic
доступ к этой функции H / W, если она доступна). Пожалуйста, обратите внимание, чтоstd::atomic
может вернуться к другой блокировке, если H / W блокировка недоступна для заблокированного типа.std::atomic
.3. Эта ментальная модель слишком упрощена, чтобы действительно добиться прогресса, но производители процессоров рассматривают свои контроллеры памяти как коммерческую тайну, поэтому у вас не так много способов сделать ее более точной. У каждого процессора есть способ атомарного обновления памяти с помощью определенного набора инструкций. Это все, что делает std::atomic, используя эти инструкции. Другие ядра, конечно, могут быть остановлены, когда выполняется такое обновление, вам должно быть немного не повезло. Или напишите неоптимальный код.
4. Я просто хотел знать, зачем нужен эксклюзивный доступ к строке кэша, когда атомарная операция сама по себе атомарна для оборудования…
Ответ №1:
Прежде всего: это зависит!
1.) Если система блокирует строку кэша, это не имеет никакого отношения к c . Это вопрос о том, как организован кэш и особенно о том, как инструкции ассемблера работают с кэшем. Это вопрос к архитектуре процессора!
2.) То, как компилятор выполняет атомарную операцию, зависит от реализации. Какие инструкции ассемблера будут сгенерированы для выполнения атомарной операции, может варьироваться от компилятора к компилятору и даже в разных версиях.
3.) Как я знаю, полная блокировка строки кэша — это только запасной вариант, если не может быть выполнено «более умное» уведомление / синхронизация других ядер, обращающихся к тем же строкам кэша. Но обычно задействован не только один кэш. Подумайте о многоуровневой архитектуре кэша. Некоторые кэши видны только одному ядру! Таким образом, существует необходимость выполнения также большего количества операций с системой памяти, таких как блокировка строки. Вам также придется перемещать данные с разных уровней кэша, даже если задействовано несколько ядер!
4.) С точки зрения c , атомарная операция — это не только отдельная операция. То, что действительно произойдет, зависит от параметров упорядочения памяти для атомарной операции. Поскольку атомарные операции часто используются для синхронизации между потоками, для одной атомарной операции RMW необходимо выполнить гораздо больше действий! Чтобы получить представление о том, что все должно быть сделано, вы должны предоставитьhttps://www.cplusplusconcurrencyinaction.com / шанс. Здесь рассматриваются детали барьеров памяти и упорядочения памяти.
5.) Блокировка строки кэша (если это действительно происходит) не должна приводить к блокировкам вращения или другим вещам на других ядрах, поскольку доступ к самой строке кэша занял всего несколько тактов. В зависимости от архитектуры он просто «удерживает» другое ядро в течение некоторых циклов. Может случиться так, что «спящее» ядро может параллельно выполнять другие действия в другом канале. Но, эй, это очень специфично для аппаратного обеспечения.
Как уже указано в комментарии: взгляните на https://fgiesen.wordpress.com/2014/08/18/atomics-and-contention /, это дает некоторые подсказки, что может произойти с когерентностью кэша и блокировкой.
Существует гораздо больше, чем скрытая блокировка. Я полагаю, что ваш вопрос царапает только на поверхности!
Для практического использования: Не думайте о! Производители компиляторов и архитекторы процессоров проделали очень хорошую работу. Вы, как программист, должны измерять производительность своего кода. С моей точки зрения: не нужно думать о том, что произойдет, если строки кэша заблокированы. Вы должны писать хорошие алгоритмы и думать о хорошей организации памяти для ваших программных данных и меньшем количестве взаимосвязей между потоками.