std :: merge, используя 2 массива mmaped? - PullRequest
2 голосов
/ 31 января 2011

Я создаю два текстовых файла с целым числом, записанным в каждой строке. Я прочитал их с диска, и я хотел сделать сортировку по ним. Два входных файла «1piece0» и «1piece1» имеют список отсортированных целых чисел. Выходной файл имеет размер, объединяющий два файла, но не так много целых чисел. Проблема: два входных файла имеют 25430000 строк, в то время как выходной файл должен иметь 50860000 строк, но в нем всего 17259463 строки. Это мой текущий код.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <algorithm>

#define FILESIZE 25430000 * sizeof(int)
#define FILE0 279288034
#define FILE1 279287226
int main()
{
    int i;
    int fd;
    int fd2;
    int fd3;
    int result;
    int *map;
    int *map2;
    int *map3;

    fd3 = open( "file.out", O_RDWR | O_CREAT | O_TRUNC, (mode_t)0755);
    if ( fd3 == -1 ) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }
    result = lseek(fd3, FILE0 + FILE1 - 1, SEEK_SET );
    if(result == -1) {
        close(fd);
        perror("Error calling lseek\n");
        exit(EXIT_FAILURE);
    }

    result = write(fd3,"",1);
    if( result != 1 ) {
        close(fd3);
        perror("error writing last byte");
        exit(EXIT_FAILURE);
    }
    map3 =(int *) mmap(0, FILE0 + FILE1, PROT_READ | PROT_WRITE, MAP_SHARED, fd3, 0);
    if( map == MAP_FAILED ) {
        close(fd);
        perror("Error mmapinG fd3");
        exit(EXIT_FAILURE);
    }


    fd = open( "1piece0", O_RDONLY );
    if( fd == -1 ) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    map = (int *)mmap(0, FILE0, PROT_READ, MAP_SHARED, fd, 0 );
    if( map == MAP_FAILED ) {
        close(fd);
        perror("error mapping file");
        exit(EXIT_FAILURE);
    }

    fd2 = open( "1piece1", O_RDONLY );
    if( fd2 == -1 ) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    map2 = (int *)mmap(0, FILE1, PROT_READ, MAP_SHARED, fd2, 0 );
    if( map == MAP_FAILED ) {
        close(fd2);
        perror("error mapping file");
        exit(EXIT_FAILURE);
    }

//  while(1);
    std::merge( map, map + 25430000, map2, map2 + 25430000, map3 );

    if(munmap(map, FILE0 ) == -1 ) {
        perror("error unmapping map");
    }
    close(fd);

    if(munmap(map3, FILE0 + FILE1 ) == -1 ) {
        perror("error unmapping map3");
    }
    close(fd3);

    if(munmap(map2, FILE1 ) == -1 ) {
        perror("error unmapping map2");
    }
    close(fd2);

    return 0;
}

Подскажите, пожалуйста, что я делаю не так?

Обновление: под строками я имею в виду целое число, а затем символ новой строки.

Ответы [ 2 ]

2 голосов
/ 31 января 2011

Вы не можете обрабатывать текстовые строки как двоичные двоичные объекты, чтобы манипулировать ими как указателями типа int.

Вы можете обрабатывать текстовые файлы как текст, который будет извлечен и использован :

void merge_ints(std::istream &a_in, std::istream &b_in, std::ostream &out) {
  int a, b;
  std::istream *remaining = 0;
  if (!(a_in >> a)) {
    remaining = &b_in;
  }
  else if (!(b_in >> b)) {
    out << a << '\n';
    remaining = &a_in;
  }
  else while (a_in && b_in) {
    if (a < b) {
      out << a << '\n';
      if (!(a_in >> a)) {
        out << b << '\n';
        remaining = &b_in;
      }
    }
    else {
      out << b << '\n';
      if (!(b_in >> b)) {
        out << a << '\n';
        remaining = &a_in;
      }
    }
  }
  for (int x; *remaining >> x;) {
    out << x << '\n';
  }
}

Использование std :: merge :

void merge_ints(std::istream &a, std::istream &b, std::ostream &out) {
  typedef std::istream_iterator<int> In;
  std::merge(In(a), In(), In(b), In(), std::ostream_iterator<int>(out, "\n"));
}

int main() {
  stringstream a ("1\n3\n5\n"), b ("2\n4\n6\n7\n"), out;
  merge_ints(a, b, out);
  cout << out.str();
}
2 голосов
/ 31 января 2011

Что вы подразумеваете под "линиями"?

Когда вы отображаете карту памяти, она обрабатывает данные как память, а здесь вы читаете их как массив целых чисел.Поэтому входные данные должны быть в собственном двоичном формате (то есть с байтами, сохраненными таким же образом, с тем же размером и тем же порядком байтов), а 25430000 - это число целых чисел, которые вы читаете из каждой коллекции.

как хранятся ваши данные?

Здесь много "магических чисел".

...