Вот минимальный пример кода:
Тема Writer:
Код: Выделить всё
#include
#include
#include
std::atomic shared_value{0};
void writer() {
while (true) {
size_t writer_local_value = shared_value.load(); // Read
writer_local_value *= 5; // Modify
shared_value.store(writer_local_value); // Store
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // Simulating delay
}
}
Код: Выделить всё
void reader() {
size_t last_seen_value = 0;
while (true) {
size_t current_value = shared_value.load(); // Read
if (current_value != last_seen_value) {
last_seen_value = current_value;
// Perform some operation when value is updated
}
}
}
Платформа: x86_64
ОС: Ubuntu
Инструмент измерения промахов в кэше: perf_event_open
Наблюдение:
Когда записывающее устройство выполняет операцию чтения-изменения-сохранения, я наблюдаю два L1D промахи в кэше для shared_value:
Один во времяshared_value.load() (чтение).
Другой во время Shared_value.store() (запись).
Однако, если я заменю код автора простым вызовом Shared_value.store() без какой-либо предварительной загрузки, я увижу только одну ошибку в кэше L1D.
Например :
Код: Выделить всё
void writer_simple() {
while (true) {
shared_value.store(42); // Only store
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
Вопрос:
Почему операция чтения-изменения-сохранения в средстве записи приводит к двум промахам в кэше L1D вместо одного?
Разве строка кэша не должна быть уже признана недействительной и выбрана во время первоначальной загрузки, и, таким образом, при последующем сохранении не должно происходить никаких дополнительных промахов?
Что является причиной этого? несоответствие, поскольку протокол MESI должен был привести только к одной ошибке в кэше?
Подробнее здесь: https://stackoverflow.com/questions/792 ... ead-modify