Я использую Google Benchmark для тестирования на столкновения в кэше данных L1 на машине x86. Вот контрольный код: < /p>
void bmRead(benchmark::State& state) {
struct alignas(64) Line {
char x[64];
Line() {}
};
constexpr int sz = 1024;
Line* lines = new Line[sz];
int ind = 0;
int steps = state.range(0);
while (state.KeepRunning()) {
for (int i = 0; i < 10; i++) {
ind += steps;
ind %= sz;
/*volatile*/ char val = lines[ind].x[0];
benchmark::DoNotOptimize(val);
benchmark::ClobberMemory();
}
}
}
BENCHMARK(bmRead)->RangeMultiplier(2)->Range(1, 512);
< /code>
ожидаемое поведение < /h1>
Идея состоит в том, чтобы вызвать конфликты с установкой кэша L1. L1D в этом процессоре представляет собой VIPT (Addr Bits [6–11] выберите набор кэша) и является 8-часовым ассоциативным, так что только 8 линий кэша могут сосуществовать за набор. В Bmread/64 мы получаем доступ к каждой 64-й кэш-линии → все строки карты на один и тот же набор кэша. Рабочий набор составляет 1024/64 = 16 строк, которые превышают ассоциативность (8) и должны вызывать выселения. С другой стороны, Bmread/128 Рабочий набор только касается 8 строк (подходит в SET), поэтому он должен работать нормально.
Результаты соответствуют ожиданию, если я использую летание в чтении:
CPU Caches:
L1 Data 32 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 512 KiB (x8)
L3 Unified 16384 KiB (x1)
Load Average: 0.29, 0.35, 0.19
-----------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------
bmRead/1 15.5 ns 15.5 ns 45195244
bmRead/2 15.5 ns 15.5 ns 45187565
bmRead/4 15.5 ns 15.5 ns 45156433
bmRead/8 15.5 ns 15.5 ns 45107741
bmRead/16 15.6 ns 15.5 ns 45115926
bmRead/32 15.5 ns 15.5 ns 45614777
bmRead/64 25.2 ns 25.2 ns 26902942
bmRead/128 18.3 ns 18.3 ns 38179996
bmRead/256 15.6 ns 15.6 ns 44976974
bmRead/512 15.5 ns 15.5 ns 45184535
Но когда я удаляю летучую и полагаясь только на донотоптимизацию (val) , время все почти идентичны:
-----------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------
bmRead/1 14.2 ns 14.2 ns 48847532
bmRead/2 14.4 ns 14.4 ns 49097537
bmRead/4 14.4 ns 14.4 ns 48728445
bmRead/8 14.4 ns 14.4 ns 48684336
bmRead/16 14.6 ns 14.6 ns 48684349
bmRead/32 14.5 ns 14.5 ns 47601341
bmRead/64 14.4 ns 14.4 ns 48734250
bmRead/128 14.4 ns 14.4 ns 48585062
bmRead/256 14.4 ns 14.4 ns 48563453
bmRead/512 14.8 ns 14.8 ns 48398019
< /code>
Кажется, чтение полностью оптимизируется. Я ожидал, что Donotoptimize (val) заставит компилятор сохранить нагрузку, но это не так.
Я посмотрел на разборку. С GCC, когда летучие не используются, кажется, нет фактической инструкции по загрузке из строк [ind] .x [0] . Вот соответствующая часть для цикла: < /p>
0x55555555fa20 add %r12d,%ebx
0x55555555fa23 mov %ebx,%eax
0x55555555fa25 sar $0x1f,%eax
0x55555555fa28 shr $0x16,%eax
0x55555555fa2b add %eax,%ebx
0x55555555fa2d and $0x3ff,%ebx
0x55555555fa33 sub %eax,%ebx
0x55555555fa35 movslq %ebx,%rax
0x55555555fa38 shl $0x6,%rax
0x55555555fa3c dec %edx
0x55555555fa3e jne 0x55555555fa20
< /code>
Интересно, что с помощью Clang нагрузка присутствует в сгенерированном машинном коде даже без летучих, и временные районы соответствуют моим ожиданиям. < /p>
Вопрос < /h1>
Почему GCC удаляет нагрузку, даже если Donotoptize (al) не должно предотвратить это? Читать из памяти? Почему Кланг ведет себя «правильно» здесь, а GCC - нет? Какая часть моего понимания неверна.
Дополнительная информация
Я также попробовал заполнительную строку* line = new Line [sz]; со случайными значениями перед циклом эталона, но это не оказало последствия на поведение эталона.
gcc: 13.3.0
clang: 13.3.0
clang. /> Команда: g ++ -O3 -march = Native -g file.cpp -lbenchmark -lpfm && ./a.out -benchmark_filter = read
template
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
#if defined(__clang__)
asm volatile("" : "+r,m"(value) : : "memory");
#else
asm volatile("" : "+m,r"(value) : : "memory");
#endif
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... ior-in-gcc
CACH CACHE L1D: Google Clarkmark Donotoptimize VS ровное поведение в GCC против Clang ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
MacOS Clang Compiler выпуск (Apple Clang версия 17.0.0 (Clang-1700.0.13.5))))
Anonymous » » в форуме C++ - 0 Ответы
- 9 Просмотры
-
Последнее сообщение Anonymous
-