从HDD读取不遵循计算机字节对齐的文件时的性能问题

时间:2010-09-29 18:28:58

标签: c++ performance file-io

我有一个使用50字节数据结构的文件格式(.STL,立体光刻,结构是标准的,不能更改。不要与标准模板库混淆)。从HD读取直接导致读取错误的数据,因为50个字节不是4的倍数。

在整个50字节结构中,我只需要36个字节。我现在用来提取数据的方法是手动将文件的读取位置偏移到下一组数据开始的位置,将36个字节读入临时变量,然后将数据转储到临时变量中进入它在阵列上的正确位置。

这是代码块:

threePoints* output = new threePoints [numTriangles]; // create an array to hold the entire file
threePoints* temp = new threePoints [1]; // temp variable to pull data out of each "cell"

// extract each triangle individualy
for (int i = 0; i < numTriangles; i++)
{
    stlFile.seekg (96 + i * 50, ios::beg);  //read vertex data and put them into tempoary array
                                            // offset = 80 header + 4 #triangles + 12 normal vector
    stlFile.read(reinterpret_cast<char*>(temp), (36)); // read the next 36 data blocks into holder, 3 points * 3 axis * 4 bytes per float
    output[i] = temp[0]; // dump values in holder into proper array
}

此方法有效,但速度很慢。我将如何做到这一点,以使其更快,更有效?

编辑:我知道手动禁用字节对齐可以解决这个问题但我需要密集使用生成的数组并多次迭代它。我被告知禁用字节对齐会导致性能问题,因此我避免使用它。

3 个答案:

答案 0 :(得分:6)

而不是做一堆小寻求&amp;读取,分配一个大缓冲区(比如足够1000个结构)并一次读取一堆记录。 (然后遍历该缓冲区,复制出你需要的36字节块)。

答案 1 :(得分:0)

使用#pragma pack(1,push)#pragma pack(pop)对结构定义进行括号。这得到了大多数编译器的支持。然后不应该添加自动填充。

GCC manual声称它是微软的兼容性功能,但它一直存在......可能比GCC本身更长。

答案 2 :(得分:0)

我没有要测试的STL数据但是这样的事情怎么样?...

#include <fstream>

#pragma pack(push, 1)

struct stl_hdr {
   unsigned int header[80];
   unsigned int triangle_cnt;
};

struct triangle {
   float norm;
   float v1;
   float v2;
   float v3;
   short attr_cnt;
};

#pragma pack(pop)

using namespace std;

int main(int argc, char* argv[]) {
   ifstream file(argv[1], ios::in | ios::binary);

   if (file.is_open()) {
      stl_hdr hdr;
      file.read((char*)&hdr, sizeof(hdr));

      triangle* tris = new triangle[hdr.triangle_cnt];

      file.read((char*)tris, hdr.triangle_cnt * sizeof(triangle));

      file.close();
   }

   return 0;
}

我根据Wikipedia's description of the STL format创建了两个结构。上面的代码假设您的代码执行了相同的操作......属性计数为零。我遗漏了错误处理/清理。