C эффективный способ чтения файла из 20000000 строк - PullRequest
0 голосов
/ 26 октября 2018

Я пытаюсь прочитать огромный набор данных из 20 миллионов строк, в каждой строке есть огромное количество (на самом деле я храню число в unsigned long long переменных), например: 1774251443, 8453058335, 19672843924, и такна ...

Я разработал простую функцию для этого, я покажу ниже

void read(char pathToDataset[], void **arrayToFill, int arrayLength) {
    FILE *dataset = fopen(pathToDataset, "r");
    if (dataset == NULL ) {
        printf("Error while opening the file.\n");
        exit(0); // exit failure, it closes the program
    }

    int i = 0;

    /* Prof. suggestion: do a  malloc RIGHT HERE, for allocate a 
     * space in memory in which store the element
     * to insert in the array
     */

    while (i < arrayLength && fscanf(dataset, "%llu", (unsigned long long *)&arrayToFill[i]) != EOF) {

        // ONLY FOR DEBUG, it will print 
        //printf("line: %d.\n", i);  20ML of lines!

        /* Prof. suggestion: do another malloc here, 
         * for each element to be read. 
         */

        i++;
    }

    printf("Read %d lines", i);
    fclose(dataset);
}

параметр arrayToFill имеет тип void** из-за цели упражнения.Каждая функция должна выполняться по универсальному типу, и массив потенциально может быть заполнен данными любого типа (в этом примере это огромные числа, но может содержать огромные строки, целые числа и т. Д.).

Я не понимаю, почему я должен делать 2 malloc звонков, не достаточно ли одного?

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Я придумала это решение POSIX, посмотрите, поможет ли оно

#include <unistd.h> //for read, write, lseek
#include <stdio.h> //fprintf
#include <fcntl.h> //for open
#include <string.h> //
#include <stdlib.h> // for exit and define
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char * argv[])
{
  int fd; // file descriptor
  char * buffer; //pointer for the malloc

  if(argc < 2)
  {
    fprintf(stderr, "Insert the file name as parameter\n");
    exit(EXIT_FAILURE);
  }

if((fd =  open(argv[1], O_RDONLY)) == -1)// opens the file in read-only mode
{
  fprintf(stderr, "Can't open file\n");
  exit(EXIT_FAILURE);
}


off_t bytes = lseek(fd, 0, SEEK_END); // looks at how many bytes the file has
              lseek(fd, 0, SEEK_SET); // returns the file pointer to the start position

buffer = malloc(sizeof(char)*bytes); // allocates enough memory for reading the file

int r = read(fd, buffer, bytes); //reads the file

if(r == -1)
{
  fprintf(stdout, "Error reading\n");
  exit(EXIT_FAILURE);
}

fprintf(stdout, "\n%s", buffer); // prints the file

close(fd);
exit(EXIT_SUCCESS);

}
0 голосов
/ 26 октября 2018

В качестве первого вопроса представьте malloc как вызов памяти для хранения ряда N объектов, каждый из которых имеет размер S. Когда у вас есть параметры void ** arrayToFill, int arrayLength, вы говорите, что этот массив будет содержать arrayLength количество указателей размера sizeof(void*).Это первое выделение и вызов malloc.

Но члены этого массива являются указателями, которые предназначены для хранения массивов или, по сути, памяти какого-либо другого объекта.При первом вызове malloc выделяется только память для хранения void* каждого элемента массива, но для памяти каждого отдельного члена массива требуется собственный вызов malloc().

Эффективное чтение строки

Что касается другого вопроса, выполнение большого количества небольших выделений памяти, а затем освобождение их (при условии, что вы сделаете это, в противном случае вы потеряете много памяти), выполняется очень медленно.Однако снижение производительности для задач, связанных с вводом / выводом, в большей степени зависит от количества вызовов, чем для количества выделяемой памяти.

Ваша программа прочитает весь файлв память, и выделите массив unsigned long long для 20 миллионов, или столько целых чисел, которые вы ожидаете обработать.Таким образом, вы можете анализировать содержимое файла, использовать функцию strtol из <stdlib.h> и по очереди копировать результирующий long в ваш большой массив.

Таким образом, вы используете только 2-3большие выделения памяти и освобождения.

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