местах. Но PowerPC relaxed все равно будет медленным для этого теста, потому что он по-прежнему требует, чтобы хранилище фиксировало L1D, а не просто находилось в буфере хранилища, так что вы могли бы испытать пинг-понг в строке кэша.

трите на этот фрагмент:

#include <atomic>
#include <thread>

typedef volatile unsigned char Type;
// typedef std::atomic_uchar Type;

void fn(Type *p) {
    for (int i=0; i<500000000; i++) {
        (*p)++;
    }
}

int main() {
    const int N = 4;

    std::thread thr[N];
    alignas(64) Type buffer[N*64];

    for (int i=0; i<N; i++) {
        thr[i] = std::thread(&fn, &buffer[i*1]);
    }

    for (int i=0; i<N; i++) {
        thr[i].join();
    }

}

Эта маленькая программа многократно увеличивает четыре смежных байта из четырех разных потоков. Ранее я использовал правило: не используйте одну и ту же строку кэша из разных потоков, так как совместное использование строки кэша плохо. Так что я ожидал, что версия четыре потока (N=4) намного медленнее, чем однопоточная версия (N=1).

Тем не менее, это мои измерения (на процессоре Haswell):

N = 1: 1 секN = 4: 1,2 с

ТакN=4 не намного медленнее. Если я использую разные строки кэша (замените*1 с участием*64), тогдаN=4 становится немного быстрее: 1,1 сек.

Те же измерения для атомарного доступа (поменяйте местами комментарии наtypedef), та же строка кэша:

N = 1: 3,1 сN = 4: 48 с

Так чтоN=4 дело гораздо медленнее (как я и ожидал). Если используются разные строки кэша, тоN=4 имеет аналогичную производительность какN=1: 3,3 сек.

Я не понимаю причину этих результатов. Почему бы мне не получить серьезное замедление неатома,N=4 кейс? Четыре ядра имеют одинаковую память в своих кешах, поэтому они должны как-то их синхронизировать, не так ли? Как они могут работать почти идеально параллельно? Почему атомный корпус серьезно замедляется?

Я думаю, что мне нужно понять, как память обновляется в этом случае. В начале ни одного ядра не былоbuffer в своих кешах. После одногоfor итерация (вfn) все 4 ядра имеютbuffer в своих строках кэша, но каждое ядро ​​записывает свой байт. Как эти строки кэша синхронизируются (в неатомарном случае)? Как кеш знает, какойбайт грязный? Или есть какой-то другой механизм для обработки этого случая? Почему этот механизм намного дешевле (на самом деле, он почти бесплатен), чем атомарный?

Ответы на вопрос(2)

Ваш ответ на вопрос