Самый быстрый способ чтения данных из множества файлов ASCII - PullRequest
1 голос
/ 12 февраля 2011

для упражнения в колледже, которое я уже представил, мне нужно было прочитать файл .txt, который содержал много названий изображений (по 1 в каждой строке).Затем мне нужно было открыть каждое изображение в виде файла ascii, прочитать их данные (изображения в формате ppm) и выполнить с ними ряд действий.Дело в том, что я заметил, что моя программа затрачивала 70% времени на чтение данных из файловой части, а не на другие вычисления, которые я делал (нахождение количества повторений каждого пикселя с помощью хеш-таблицы, нахождение различийпикселей между 2 изображениями и т. д.), что я нашел довольно странным, если не сказать больше.

Вот как выглядит формат ppm:

P3 //This value can be ignored when reading the file, because all image will be correctly formatted
4 4
255 //This value can be also ignored, will be always 255.
0  0  0    0  0  0    0  0  0   15  0 15
0  0  0    0 15  7    0  0  0    0  0  0
0  0  0    0  0  0    0 15  7    0  0  0
15  0 15    0  0  0    0  0  0    0  0  0

Вот как я читалданные из файлов:

ifstream fdatos;
fdatos.open(argv[1]); //Open file with the name of all the images

const int size = 128;
char file[size]; //Where I'll get the image name

Image *img;
while (fdatos >> file) { //While there's still images anmes left, continue
    ifstream fimagen;
fimagen.open(file);  //Open image file
img = new Image(fimagen); //Create new image object with it's data file
    ………
    //Rest of the calculations whith that image
    ………
delete img; //Delete image object after done 
    fimagen.close(); //Close image file after done
}

fdatos.close();

А внутри объекта изображения читайте данные примерно так:

const int tallafirma = 100;
char firma[tallafirma];
fich_in >> std::setw(100) >> firma; // Read the P3 part, can be ignored

int maxvalue, numpixels;
fich_in >> height >> width >> maxvalue; // Read the next three values
numpixels = height*width;
datos = new Pixel[numpixels];

int r,g,b; //Don't need to be ints, max value is 256, so an unsigned char would be ok.
for (int i=0; i<numpixels; i++) {
   fich_in >> r >> g >> b;
   datos[i] = Pixel( r, g ,b);
}
//This last part is the slow one, 
//I thing I should be able to read all this data in one single read 
//to buffer or something which would be stored in an array of unsigned chars, 
//and  then I'd only need to to do:
//buffer[0] -> //Pixel 1 - Red data
//buffer[1] -> //Pixel 1 - Green data
//buffer[2] -> //Pixel 1 - Blue data

Итак, есть идеи?Я думаю, что могу немного улучшить его, читая все в массиве за один вызов, я просто не знаю, как это сделать.

Кроме того, возможно ли узнать, сколько изображений будет в"индексный файл"?Возможно ли узнать количество строк в файле? (Потому что в каждой строке есть одно имя файла ..)

Спасибо !!

РЕДАКТИРОВАТЬ: Вот как я измерил время.

#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
  struct timeval t;
  struct timezone tzp;
  gettimeofday(&t, &tzp);
  return t.tv_sec + t.tv_usec*1e-6;
}

double start = get_time();
//Everything to be measured here.
double end = get_time();

cout << end-start << endl;

Ответы [ 2 ]

1 голос
/ 12 февраля 2011

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

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

void *memory = malloc(sizeof(Image)); //reusable memory. 

//placement new to construct the object in the already allocated memory!
img = new (memory) Image(fimagen);

//...

img->~Image(); //calling the destructor

//when you're done free the memory
free(memory); //use free, as we had used malloc when allocating!

Аналогично, вы можете повторно использовать память в Image class, особенно в этой строке:

 datos = new Pixel[numpixels];

И, наконец, вместо чтения RGB в локальные переменные, а затем копирования их в данные изображения, это не так уж и элегантно, так что небольшое улучшение может бытьсделано и здесь,

 //this is yours : temporaries, and copying!
 fich_in >> r >> g >> b;
 datos[i] = Pixel( r, g ,b);

 //this is mine : no temporaries, no copying. directly reading into image data!
 fich_in >> datos[i].r >> datos[i].g >> datos[i].b;

Кроме этого, я не думаю, что есть много возможностей улучшить производительность вашего кода!

0 голосов
/ 12 февраля 2011

Невозможно вычислить количество строк в текстовом файле без чтения всего файла.

Что касается других оптимизаций, используйте команду time (если вы работаете в Unix / Linux), чтобы проверить, использует ли программа много времени «пользователя» (фактические вычисления) по сравнению со временем «настенного часа» (всего время между началом и концом процесса). Если нет, то вы, вероятно, ожидаете диск или сеть.

...