Понимание производительности и поведения инструкции clwb

Я пытаюсь понять производительность чтения / записи инструкции clwb и проверить, как она изменяется в случае записи в строку кеша по сравнению с тем, когда я ее только читаю. Я ожидаю, что для случая записи затраченное время должно быть больше, чем для случая чтения. Чтобы проверить то же самое, вот небольшой фрагмент кода, который я запускаю на процессоре Intel Xeon (skylake) и использую энергонезависимую память (NVM) для хранилища чтения и записи.

/* nvm_alloc allocates memory on NVM */
uint64_t *array = (uint64_t *) nvm_alloc(pool, 512);
uint64_t *p = &array[0];
/* separated p & q by the size of write unit in Optane (256B) */
uint64_t *q = &array[32];

uint64_t time_1 = 0;
uint64_t time_2 = 0;
uint64_t start;

volatile uint64_t x;
for(int i = 0; i < 1000000; i++)
{
        /* issues an mfence instruction */
        mfence();
        /* this is for the read case, bring p into cache */
        /* commented read case */
        //x = *p;
        /* this is for the write case, update cacheline containing p */
        *p = *p + 1;
        *q = *q + 1;
        /* rdtscp here to flush instruction pipeline */
        start = rdtscp();
        /* issue clwb on cacheline containing p */
        clwb(p);
        time_1 += rdtsc() - start;

        start = rdtsc();
        clwb(q);
        time_2 += rdtsc() - start;
}

Поскольку clwb явно не вытесняет строку кэша, следующие итерации чтения, возможно, будут обслуживаться из самого кеша. В случае записи строка кэша модифицируется на каждой итерации, а затем выдается clwb для ее обратной записи. Однако время, затрачиваемое на запись, почти равно времени чтения, которое я не могу понять. Если время записи не включает время обратной записи грязной строки кэша в память (или контроллер памяти)


person skm    schedule 10.03.2020    source источник
comment
К сожалению, CLWB не гарантирует, что строка кэша останется присутствующей; в SKX он работает так же, как CLFLUSHOPT. Впрочем, введение поддержки заглушек, пожалуй, лучше, чем заставлять будущих пользователей проверять поддержку процессора, чтобы избежать SIGILL.   -  person Peter Cordes    schedule 10.03.2020
comment
@PeterCordes плюс код синхронизации неверен, потому что rdtsc не упорядочен с clwb как во время компиляции, так и во время выполнения.   -  person Hadi Brais    schedule 10.03.2020
comment
@HadiBrais, не могли бы вы объяснить, что вы имели в виду. Я обновил код, чтобы отразить фактическое измерение. Я пишу в две разные строки кеша (разделенные размером блока записи в Optane) и использую rdtsc, за исключением первой, поскольку я хочу чередовать две операции clwb.   -  person skm    schedule 10.03.2020
comment
Если вы позволите rdtsc прочитать TSC до clwb завершения, это бессмысленно, и вы даже не рассчитываете clwb выход на пенсию, не говоря уже о завершении всего пути до DRAM или где бы то ни было. Все, что вы рассчитываете, - это выполнение вне очереди rdtsc после выдачи clwb. И даже не потому, что rdtscp только следит за выполнением предыдущих инструкций; он также не останавливает выполнение более поздних инструкций до того, как закончит считывание времени. А добавленный вами бит еще хуже: и start, и stop - это неупорядоченные rdtsc инструкции. Кроме того, зачем использовать два подряд rdtsc? Просто прочтите время один раз   -  person Peter Cordes    schedule 10.03.2020
comment
Я понимаю, что @PeterCordes, читая один за другим rdtsc, вроде как не нужно. Я хотел чередовать две инструкции clwb, поскольку они не упорядочены относительно друг друга, и измерить их индивидуальное время. Использование rdtscp не поможет, так как будет ждать завершения предыдущего clwb, что не позволит чередовать, любые подсказки к тому, как это можно сделать.   -  person skm    schedule 10.03.2020
comment
Что вы подразумеваете под чередованием двух операций clwb? Также процессоры Skylake не поддерживают постоянные карты памяти Optane. Возможно, вы используете Cascade Lake (SP 2-го поколения)?   -  person Hadi Brais    schedule 10.03.2020
comment
@HadiBrais Поскольку инструкции clwb для разных строк кэша не упорядочены относительно друг друга, я не хочу, чтобы первый clwb заканчивался до выдачи второго. Это то, что я называю чередованием.   -  person skm    schedule 10.03.2020
comment
Я вижу, что вы пытаетесь сделать (надеясь, что rdtsc заказан по CLWB, но не по чему-либо еще), но, к сожалению для вас, это не так, как все работает. Если вы хотите, чтобы выполнение перекрывалось, вы не можете рассчитывать время отдельно, только для всего перекрывающегося черного ящика того, что ЦП делал во время этого перекрытия. (Существуют счетчики производительности, такие как frontend_retired.latency_ge_64 и mem_trans_retired.load_latency_gt_64, которые могут сказать вам что-то для каждой инструкции даже во время OoO exec, но это очень ограничено.)   -  person Peter Cordes    schedule 10.03.2020
comment
@PeterCordes благодарит за полезные ссылки.   -  person skm    schedule 11.03.2020
comment
Привет, как уже упоминал @HadiBrais, процессоры Skylake не поддерживают постоянную память Optane. С другой стороны, в архитектуре Cascade lake с модулями NVM DIMM у вас есть два режима конфигурации: режим памяти и режим прямого приложения. Итак, я хотел добавить, что в прямом режиме приложения две clwb инструкции, скорее всего, упорядочены относительно друг друга. Я заметил, что Clwb упорядочен относительно следующей операции записи в ту же строку кэша, которая дает поведение, подобное clflush, поэтому было бы не совсем правильно предполагать, что вы можете чередовать два clwbs.   -  person Ana Khorguani    schedule 24.03.2020