Отдельный цикл замедляет независимый предыдущий цикл?

Как отдельный цикл может повлиять на производительность независимого предыдущего цикла?

Мой первый цикл читает несколько больших текстовых файлов и считает строки /строки. После malloc второй цикл заполняет выделенную матрицу.

Если второй цикл закомментирован, первый цикл занимает 1,5 секунды. Однако компиляция WITH второго цикла замедляет первый цикл, который теперь занимает 30-40 секунд!

Другими словами: второй цикл как-то замедляет первый цикл. Я пытался изменить область видимости, изменить компиляторы, изменить флаги компилятора, изменить сам цикл, перенести все в main (), использовать boost :: iostream и даже поместить один цикл в общую библиотеку, но в каждой попытке та же проблема сохраняется!

Первый цикл выполняется до тех пор, пока программа не скомпилируется со вторым циклом.


РЕДАКТИРОВАТЬ: Вот полный пример моей проблемы ------------>

#include <iostream>
#include <vector>
#include "string.h"
#include "boost/chrono.hpp"
#include "sys/mman.h"
#include "sys/stat.h"
#include "fcntl.h"
#include <algorithm>

unsigned long int countLines(char const *fname) {
    static const auto BUFFER_SIZE = 16*1024;
    int fd = open(fname, O_RDONLY);
    if(fd == -1) {
        std::cout << "Open Error" << std::endl;
        std::exit(EXIT_FAILURE);
    }

    posix_fadvise(fd, 0, 0, 1); 
    char buf[BUFFER_SIZE + 1];
    unsigned long int lines = 0;

    while(size_t bytes_read = read(fd, buf, BUFFER_SIZE)) {
        if(bytes_read == (size_t)-1) {
            std::cout << "Read Failed" << std::endl;
            std::exit(EXIT_FAILURE);
        }
        if (!bytes_read)
            break;

        int n;
        char *p;
        for(p = buf, n=bytes_read ; n > 0 && (p = (char*) memchr(p, '\n', n)) ; n = (buf+bytes_read) - ++p)
            ++lines;
    }
    close(fd);
    return lines;
}

int main(int argc, char *argv[])
{
    // initial variables
    int offset = 55;  
    unsigned long int rows = 0;
    unsigned long int cols = 0;
    std::vector<unsigned long int> dbRows = {0, 0, 0};
    std::vector<std::string> files = {"DATA/test/file1.csv",  // large files: 3Gb 
                                      "DATA/test/file2.csv",  // each line is 55 chars long 
                                      "DATA/test/file3.csv"};

    // find each file's number of rows 
    for (int x = 0; x < files.size(); x++) {   // <--- FIRST LOOP **
        dbRows[x] = countLines(files[x].c_str());
    }

    // define matrix row as being the largest row found 
    // define matrix col as being 55 chars long for each csv file
    std::vector<unsigned long int>::iterator maxCount;
    maxCount = std::max_element(dbRows.begin(), dbRows.end());
    rows = dbRows[std::distance(dbRows.begin(), maxCount)];   // typically rows = 72716067
    cols = dbRows.size() * offset;                            //           cols = 165 

    // malloc required space (11998151055)
    char *syncData = (char *)malloc(rows*cols*sizeof(char));

    // fill up allocated memory with a test letter
    char t[]= "x";
    for (unsigned long int x = 0; x < (rows*cols); x++) {   // <--- SECOND LOOP **
        syncData[x] = t[0];
    } 

    free(syncData);
    return 0; 
}

Я также заметил, что уменьшение количества столбцов ускоряет первый цикл.

Профилировщик указывает пальцем на эту строку:

while(size_t bytes_read = read(fd, buf, BUFFER_SIZE))

Программа простаивает в этой строке в течение 30 секунд или счетчик ожидания 230 000. В сборке счетчик ожидания происходит на:

Block 5:
lea 0x8(%rsp), %rsi
mov %r12d, %edi
mov $0x4000, %edx
callq  0x402fc0     <------ stalls on callq
Block 6:
mov %rax, %rbx
test %rbx, %rbx
jz 0x404480 <Block 18>

Я предполагаю, что при чтении из потока происходит блокировка API, но я не знаю почему?

7 голосов | спросил Harry Reed 1 22016vEurope/Moscow11bEurope/MoscowTue, 01 Nov 2016 00:02:21 +0300 2016, 00:02:21

2 ответа


0

Моя теория:

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

Если вы пару раз запускали версию без loop2 для прогрева дискового кэша, а затем запускали версию с loop2, я предсказываю, что она будет быстрой в первый раз, но медленной для дальнейших запусков без сначала разогреваем кеш диска.

Потребление памяти происходит после того, как файлы были прочитаны. Это приводит к «давлению памяти» на кеш страниц (он же дисковый кеш), из-за чего он выталкивает данные из кеша, чтобы освободить место для страниц для вашего процесса записи.

Возможно, на вашем компьютере недостаточно свободной оперативной памяти для кэширования вашего рабочего набора. Закрытие вашего веб-браузера может освободить достаточно, чтобы изменить ситуацию! Или нет, поскольку ваш 11998151055 составляет 11,1 ГБ, и вы пишете каждую его страницу. (Даже каждый байт. Вы можете сделать это с помощью memset для повышения производительности, хотя я предполагаю, что вы показали, что это просто фиктивная версия )


Кстати, еще одним инструментом для изучения этого будет time ./a.out. Он может показать вам, тратит ли ваша программа все свое процессорное время в пространстве пользователя по сравнению с временем ядра («системы»).

Если user + sys добавляет к реальному времени, ваш процесс связан с процессором. Если нет, то он связан с вводом /выводом, и ваш процесс блокируется на дисковых операциях ввода /вывода (что является нормальным, поскольку подсчет новых строк должен быть быстрым).

ответил Peter Cordes 1 22016vEurope/Moscow11bEurope/MoscowTue, 01 Nov 2016 16:31:47 +0300 2016, 16:31:47
0

На ЭТОЙ СТРАНИЦЕ

"Функция close закрывает filedes дескриптора файла. Закрытие файла имеет следующие последствия:

Файловый дескриптор освобожден. Любые блокировки записей, принадлежащие процессу в файле, разблокируются. Когда все файловые дескрипторы, связанные с каналом или FIFO, закрыты, все непрочитанные данные отбрасываются. "

Я думаю, что вы могли заблокировать ресурсы при предыдущем чтении. Попробуйте закрыть файл и сообщите нам результат.

ответил Ricardo Ortega Magaña 1 22016vEurope/Moscow11bEurope/MoscowTue, 01 Nov 2016 01:59:52 +0300 2016, 01:59:52

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132