4

在我的程序中,我读入了一个文件(这里只有一个大约 200k 数据点的测试文件,之后会有数百万个数据点。)现在我要做的是:

for (int i=0;i<n;i++) {
    fid.seekg(4,ios_base::cur);
    fid.read((char*) &x[i],8);
    fid.seekg(8,ios_base::cur);
    fid.read((char*) &y[i],8);
    fid.seekg(8,ios_base::cur);
    fid.read((char*) &z[i],8);
    fid.read((char*) &d[i],8);
    d[i] = (d[i] - p)/p;
    z[i] *= cc;
}

其中 n 表示要读入的点数。

之后我再次用

for(int i=0;i<n;i++){
        fid.write((char*) &d[i],8);
        fid.write((char*) &z[i],8);

        temp = (d[i] + 1) * p;
        fid.write((char*) &temp,8);
    }

从而写入比读取快。(用clock_t测量的时间)

我的问题是现在。我在阅读时犯了一些相当愚蠢的错误,还是可以预料到这种行为?

我正在使用带有磁驱动器的 Win XP。

你的magu_

4

3 回答 3

13

你用seekg得太频繁了。我看到您正在使用它来跳过字节,但您也可以读取完整的缓冲区,然后跳过缓冲区中的字节:

char buffer[52];

for (int i=0;i<n;i++) {
    fid.read(buffer, sizeof(buffer));
    memcpy(&x[i], &buffer[4], sizeof(x[i]));
    memcpy(&y[i], &buffer[20], sizeof(y[i]));
    // etc
}

但是,您可以定义一个表示文件中数据的结构:

#pragma pack(push, 1)
struct Item
{
    char dummy1[4]; // skip 4 bytes
    __int64 x;
    char dummy2[8]; // skip 8 bytes
    __int64 y;
    char dummy3[8]; // skip 8 bytes
    __int64 z;
    __int64 d;
};
#pragma pack(pop)

然后声明这些结构的数组并一次读取所有数据:

Item* items = new Item[n];
fid.read(items, n * sizeof(Item)); // read all data at once will be amazing fast

(备注:我不知道,和的类型x,所以我在这里假设)yzd__int64

于 2013-05-28T13:33:49.253 回答
4

我个人(至少)会这样做:

for (int i=0;i<n;i++) {
    char dummy[8];
    fid.read(dummy,4);
    fid.read((char*) &x[i],8);
    fid.read(dummy,8);
    fid.read((char*) &y[i],8);
    fid.read(dummy,8);
    fid.read((char*) &z[i],8);
    fid.read((char*) &d[i],8);
    d[i] = (d[i] - p)/p;
    z[i] *= cc;
}

做一个结构,或一次读取大量数据(比如添加第二层,一次读取 4KB,然后使用一对“跳过”和“获取”不同字段的函数将是更多的工作,但可能更快)。

另一种选择是mmap在 Linux 或MapViewOfFileWindows 中使用。这种方法减少了一小部分读取文件的开销,因为将数据传输到应用程序所需的副本更少。

编辑:我应该添加“确保您进行比较测量”,如果您的应用程序要在多台机器上运行,请确保您在不止一种类型的机器上进行测量,并使用不同的磁盘驱动器、处理器和内存替代品。您真的不想调整代码,使其在您的机器上运行速度提高 50%,但在另一台机器上运行速度降低 25%。

于 2013-05-28T13:46:46.157 回答
1

assert() 语句是此代码中最重要的部分,因此如果您的平台发生变化并且您的本机类型的宽度发生变化,那么断言将失败。而不是寻找,我会读到一个虚拟区域。p* 变量使代码更易于阅读,IMO。

assert(sizeof x[0] == 8);
assert(sizeof y[0] == 8);
assert(sizeof z[0] == 8);
assert(sizeof d[0] == 8);

for (int i=0;i<n;i++) {
    char unused[8];
    char * px = (char *) &x[i];
    char * py = (char *) &y[i];
    char * pz = (char *) &z[i];
    char * pd = (char *) &d[i];

    fid.read(unused, 4);
    fid.read(px, 8);
    fid.read(unused, 8);
    fid.read(py, 8);
    fid.read(unused, 8);
    fid.read(pz, 8);
    fid.read(pd, 8);

    d[i] = (d[i] - p)/p;
    z[i] *= cc;
}
于 2013-05-28T14:19:36.907 回答