Ядро всегда пытается зафиксировать свой буфер хранилища в кэше L1d (и, таким образом, стать глобально видимым) как можно быстрее, чтобы освободить место для большего количества хранилищ.
Вы можете использовать барьер (например, atomic_thread_fence(memory_order_seq_cst
), чтобы создать поток ждать , пока его хранилища не станут глобально видимыми, прежде чем делать какие-либо дополнительные загрузки или накопления, но это работает, блокируя это ядро, а не ускорение очистки буфера хранилища.
Очевидно, чтобы избежать неопределенного поведения в C11, переменная должна быть _Atomic
. Если есть только один писатель, вы можете использовать tmp = atomic_load_explicit(&x, memory_order_relaxed)
и store_explicit из tmp+1
, чтобы избежать более дорогого хранилища seq_cst или атомарного RMW. Порядок acq / rel тоже сработает, просто избегайте seq_cst по умолчанию и избегайте atomic_fetch_add
RMW, если есть только один писатель.
Вам не нужно, чтобы вся операция RMW была атомарной, если только один поток когда-либо изменял ее, а другие потоки обращались к ней только для чтения.
Прежде чем другое ядро сможет прочитать данные, которые вы написали, оно должно пройти путь от состояния Modified в L1d ядра, которое записало его в кэш-память L3, и оттуда в L1d ядра считывателя.
Возможно, вы сможете ускорить эту часть вперед, что происходит после того, как данные покидают буфер хранилища. Но вы мало что можете сделать с пользой. Вы не хотите clflush
, что приведет к обратной записи + удалению строки кэша, поэтому другому ядру придется получить ее из DRAM, если он не попытается прочитать ее в какой-то момент (если это даже возможно).
В Ice Lake будет clwb
, что оставляет данные в кэше, а также принудительную обратную запись в DRAM. Но опять же, это заставляет данные фактически переходить на DRAM.
Tremont (преемник Goldmont Plus , серия Atom / Silvermont) имеет _mm_cldemote
(cldemote
). Это как противоположность предварительной выборке SW; это необязательный совет по производительности для записи строки кэша в L3, но не заставляет переходить на DRAM или что-либо еще.
Кроме этого, может быть, есть какая-то хитрость, такая как запись в 8 других местоположений, которые используют псевдоним того же набора в кэш-памяти L2 и L1d, вызывая исключение конфликта. Это потребовало бы дополнительного времени в потоке записи, но могло бы сделать данные более доступными для других потоков, которые хотят их прочитать.