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

C++ 从大量ASCII文件读取数据的最快方法,c++,io,buffer,ifstream,C++,Io,Buffer,Ifstream,对于我已经提交的一个大学练习,我需要阅读一个.txt文件,其中包含许多图像名称(每行1个)。 然后我需要将每个图像作为ascii文件打开,读取它们的数据(ppm格式的图像),并对它们执行一系列操作。 问题是,我注意到我的程序在从文件部分读取数据时占用了70%的时间,而不是在我正在做的其他计算中(用哈希表查找每个像素的重复次数,在两个图像之间查找不同的像素等等),至少我觉得这很奇怪 ppm格式是这样的: P3 //This value can be ignored when reading the

对于我已经提交的一个大学练习,我需要阅读一个.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
const int tallafirma=100;
查菲玛[塔拉菲玛];
fich_in>>std::setw(100)>>firma;//阅读P3部分,可以忽略
整数最大值,单位为像素;
fich_in>>高度>>宽度>>最大值;//阅读下面三个值
numpixels=高度*宽度;
datos=新像素[numpixels];
int r,g,b//不需要是整数,最大值是256,所以无符号字符就可以了。
对于(inti=0;i>r>>g>>b;
datos[i]=像素(r,g,b);
}
//最后一部分是慢的部分,
//我想我应该能够在一次读取中读取所有这些数据
//缓冲区或存储在未签名字符数组中的内容,
//然后我只需要做:
//缓冲区[0]->//像素1-红色数据
//缓冲区[1]->//像素1-绿色数据
//缓冲区[2]->//像素1-蓝色数据
那么,有什么想法吗?我想我可以在一次调用中读取一个数组的所有内容来改进它,我只是不知道如何做到这一点

此外,是否可以知道“索引文件”中将包含多少图像?是否可以知道文件的行数?(因为每行有一个文件名..)

谢谢

编辑:这就是我确定时间的方法

#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;
#包括
#包括
双倍获得时间()
{
结构时间值t;
结构时区tzp;
gettimeofday&t和&tzp);
返回t.tv_sec+t.tv_usec*1e-6;
}
双启动=获取时间();
//这里要测量的一切。
双端=获取时间();

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

因此,您可以做的一个改进是:一旦分配给程序,就重用内存

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;

除此之外,我认为在代码性能方面没有太多改进的余地!

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

因此,您可以做的一个改进是:一旦分配给程序,就重用内存

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;

除此之外,我认为在提高代码性能方面没有太大的余地!

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


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

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


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

嗯,我不知道我真的能做到这一点,我对所有这一切都很陌生。我会试试看它是否有帮助。此外,我也不太担心,只是我注意到并看到人们将整个文件读取到缓冲区,我认为这会有所改善,因为您只需要访问ss一次到磁盘???。我不知道。嗯,@Nawaz,就是这样!临时变量和RGB变量的复制。用一个小集合(30 256x256图像)测试它使时间从0.23降到0.098。神圣的烟雾xD@Nawaz,最后一件事,指向内存的无效指针是否需要手动解除分配?因为我在末尾放置了一个删除内存,但编译时出错。@Alsenes:您不能使用
delete
解除分配使用
malloc
分配的内存。总之,我添加了我试着回答这一部分。检查一下。:-)你的进步并不令人惊讶。但是我相信,如果你把文件分成大块读入缓冲区,你会得到比现在快得多的解决方案!你看,当你只读了一小部分,磁盘继续旋转时,你需要等待旋转再次到位,以便下一次读取。由于文件(特别是不是太大的文件)是以连续的裂缝写入磁盘的,因此一次性读取它们可以节省大量时间。你至少应该每次读一行,然后从该行的缓冲区中读取(你应该像Nawaz向你展示的那样重新使用)。好吧,我不知道我真的可以做到这一点,我对所有这一切都很陌生。我会试试看它是否有帮助。另外,我也不太担心,只是我注意到并看到人们将整个文件读到一个缓冲区,我想这会有所改善,因为你只能访问一次磁盘???。我不知道。嗯,@Nawaz,那是