从大量ASCII文件中读取数据的最快方法

时间:2011-02-12 15:20:11

标签: c++ io buffer ifstream

对于我已提交的大学练习,我需要阅读一个.txt文件,其中包含很多图像名称(每行1个)。 然后我需要打开每个图像作为ascii文件,并读取他们的数据(图像以ppm格式),并用它们做一系列的事情。 事情是,我注意到我的程序占用了70%的时间来读取文件部分的数据,而不是我正在做的其他计算(找到每个像素的重复次数和哈希表,找到不同的东西)两个图像之间的像素等。),我发现至少可以说是奇怪的。

这是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 个答案:

答案 0 :(得分:1)

您正在分配内存并在每个循环中删除它。如果你如此关注性能,我认为这不好。

因此,您可以做的一项改进是:在将内存分配给您的程序后重复使用

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类中重用内存,尤其是在此行:

 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;

除此之外,我认为没有太多余地可以明智地改善您的代码性能!

答案 1 :(得分:0)

如果不读取整个文件,就无法计算文本文件中的行数。

对于其他优化,使用time命令(如果你在Unix / Linux上)检查程序是否使用了大量“用户”时间(实际计算)与“wallclock”时间相比(进程开始和结束之间的总时间)。如果没有,您可能正在等待磁盘或网络。