我有 1GB 二进制文件,它基本上包含相同类型值的 3D 立方体。使用 fseek 和 fwrite 保存这种具有不同顺序([x,y,z] 或 [zx, y])的多维数据集会花费大量时间。但是其中一个软件包比我的程序要快得多。有什么方法可以使文件写入比使用 fseek/fwrite 更快?
3 回答
您不应该在文件 io 操作的内部循环中使用 fseek。为了使写入功能更快,它们会缓存写入。如果你到处寻找,你会不断地破坏缓存。
在内存中进行所有转换 - 例如在内存中旋转立方体,然后在几个连续的 fwrite 调用中写入文件。
如果您无法在内存中完全转换数据,则在内存中一次组装一个平面并写出每个平面。
@编辑:
在您的情况下,您根本不想使用 fseek 。一个也没有。
做这样的事情:
void writeCubeZYX( int* cubeXYZ, int sizeOfCubeXYZ, FILE* file )
{
int* cubeZYX = malloc( sizeOfCubeXYZ );
// all that monkey business you're doing with fseek is done inside this
// function copying memory to memory. No file IO operations in here.
transformCubeXYZ_to_ZYX( cubeXYZ, cubeZYX, sizeOfCubeXYZ );
// one big fat very fast fwrite. Optimal use of file io cache.
fwrite( file, cubeZYX, 1, sizeOfCubeXYZ );
free( cubeZYX ); // quiet pedantry.
}
@edit2:
好的,假设您不能在内存中全部转换它,然后在平面中转换它并一次写出一个平面 - 按文件顺序 - 没有 fseeks。
假设一个 [XYZ] 立方体在内存中布置为一系列 Z [XY] 矩阵。那就是你的立方体的 [XY] 平面在内存中是连续的。你想写成[ZYX]。因此,您要在文件中写出一系列 X [ZY] 矩阵。每个 [ZY] 在文件中都是连续的。
所以你做这样的事情:
void writeCubeZYX( int* cubeXYZ, int x, int y, int z, FILE* file )
{
int sizeOfPlaneZY = sizeof( int ) * y * z;
int* planeZY = malloc( sizeOfPlaneZY );
for ( int i = 0; i < X; i++ )
{
// all that monkey business you're doing with fseek is done inside this
// function extracting one ZY plane at a time. No file IO operations in here.
extractZYPlane_form_CubeXYZ( cubeXYZ, planeZY, i );
// in X big fat very fast fwrites. Near optimal use of file io cache.
fwrite( file, planeZY, 1, sizeOfPlaneZY );
}
free( planeZY ); // quiet pedantry.
}
如果你正在做大量的随机访问写作。我建议你使用 mmap。mmap 将内存页面映射到您的文件,它由操作系统控制。类似于内存交换机制。
另一种方法是您可以使用异步 IO。它由 GLIBC http://www.gnu.org/software/libc/manual/html_node/Asynchronous-I_002fO.html提供
它只是将数据放入内存中的队列中,然后创建另一个线程来管理 IO。
如果您不介意磁盘上的文件是压缩文件,那么在写入时压缩它可能会更快。这加快了速度,因为瓶颈通常是将字节写入磁盘,并且通过在写入时进行压缩,可以减少需要写入的字节数。
这当然取决于您的数据是否适合压缩。在 c++ 中压缩输出的一种选择是 gzip。例如:我如何读取/写入 gzip 压缩文件?
但是在您的情况下,这可能不适用-您的问题尚不清楚您何时/为什么要寻找。您预期的写入模式是什么?