Объясняет ли поведение кэша уменьшение времени записи C ++ в свободное хранилище? - PullRequest
1 голос
/ 04 февраля 2020

Мы профилируем сложную программу на C ++, которая выполняет несколько итераций алгоритма. Время имеет решающее значение, и мы хотим минимизировать время выполнения каждой итерации. Алгоритм таков, что время выполнения должно быть очень похожим для каждой итерации, но мы обнаруживаем, что время выполнения уменьшается с последовательными итерациями. Мы подозреваем, что за это отвечает кеш, но не можем полностью объяснить, что мы видим, основываясь на нашем понимании кешей.

Мы выполняем код на процессоре Intel Xeon с Centos 7.6, скомпилированным g ++ 7.3. 1.

Нам удалось продемонстрировать поведение, используя простую программу, показанную ниже:

#include <vector>
#include <fstream>
#include <array>
#include <chrono>
#include <iostream>

int main()
{
    std::chrono::high_resolution_clock::time_point t1;
    std::chrono::high_resolution_clock::time_point t2;

    const unsigned NUM_BUFFERS = 200;
    const unsigned BUFFER_SIZE_BYTES = 1024 * 1024;
    const unsigned NUM_TRIALS = 50;

    std::vector<uint8_t*> buffers;

    for (int buff=0; buff<NUM_BUFFERS; ++buff)
        buffers.push_back(new uint8_t[BUFFER_SIZE_BYTES]);

    std::vector<double> tAll;   // Records execution time for each buffer write
    tAll.resize(NUM_TRIALS*NUM_BUFFERS);

    unsigned indt = 0;

    // For each trial
    for ( unsigned indTrial=0; indTrial<NUM_TRIALS; indTrial++ )
    {
        // For all buffers
        for ( unsigned indBuffer=0; indBuffer<NUM_BUFFERS; indBuffer++ )
        {
            t1 = std::chrono::high_resolution_clock::now();

            // Increment contents of entire buffer
            uint8_t* p_buff = buffers.at(indBuffer);
            for ( unsigned ind=0; ind<BUFFER_SIZE_BYTES; ind++ )
            {
                p_buff[ind]++;
            }
            t2 = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> duration = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
            tAll.at(indt++) = duration.count();
        }
    }

    // Write execution times to a file
    std::ofstream fp;
    fp.open("TEST_ARTEMIS.TXT");
    double max=0;
    for ( unsigned ind=0; ind<tAll.size(); ind++ )
    {
        fp << tAll[ind] << std::endl;
    }
}

Эта программа увеличивает каждый байт серии из 200 из 1 МБ буферов. Процесс повторяется 50 раз .

Время для каждой полной записи каждого буфера записывается в файл. Если мы построим эти времена и увеличим масштаб до первых 250 операций записи в буфер, мы увидим:

enter image description here

Первая запись в буфер занимает ~ 10 мс, следующая немногие берут ~ 3 мс, следующие 200 берут ~ 2,5 мс, а затем время падает до 2 мс.

Мы не думаем, что это поведение можно объяснить простым поведением кеша, поскольку кеши L2 / L3 не являются достаточно большой, чтобы вместить все буферы, поэтому записи в кеш должны происходить на протяжении всего эксперимента. Как будто память «нагревается» и ускоряется со временем.

Может кто-нибудь предложить объяснение того, что мы видим, пожалуйста?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...