2

我正在读取大小为 4096 的数组寄存器中的文件。

我在循环之外有一个容器数组,我想按顺序将数据块“附加”到它,最快和最有效的方法是什么?

PointRecord4 * AllRegisters = new PointRecord4[ptr->Number_of_Point_records];

    if (ptr->Point_Data_Format_ID == 4)
        switch ((*ptr).Point_Data_Format_ID)
        {
        case 4:
            {
                PointRecord4 registers[4096];
                ULONG32 pointsToRead = 4096;
                ULONG32 pointsLoaded = 0;               
                ULONG32 i;

                for (i = 0; pointsLoaded < ptr->Number_of_Point_records; i += pointsToRead)
                {
                    pointsToRead =  std::min(pointsToRead, ptr->Number_of_Point_records - pointsLoaded);
                    input_file.read(PTR(&registers), sizeof(PointRecord4) * pointsToRead);
                    pointsLoaded += pointsToRead;

                    //Insert registers[4096] into AllRegisters, Appending it
                } 
            } break;
    }

我试图简单地迭代 4096 并推回向量,但这非常慢。

以下是我的完整代码:

#include "vgl.h"
#include <fstream>
#include <iostream>
#include <vector>
#include <string.h>


using namespace std;

#define PTR reinterpret_cast<char *>

#pragma pack(1)
typedef struct LasHeader
{
    char           File_Signature[4];                            // 4 Bytes
    UINT16 FileSourceID;                                         // 2 Bytes
    UINT16 Global_Encoding;                                      // 2 Bytes
    ULONG32  GUID1;                                              // 4 Bytes
    UINT16 GUID2;                                                // 2 Bytes
    UINT16 GUID3;                                                // 2 Bytes
    UCHAR  GUID4[8];                                             // 2 Bytes
    UCHAR  Version_Major;                                        // 1 Bytes
    UCHAR  Version_Minor;                                        // 1 Bytes
    CHAR           System_Identifier[32];                        // 32 Bytes
    CHAR           Generating_Software[32];                      // 32 Bytes
    UINT16 File_Creation_Day_Of_Year;                            // 2 Bytes
    UINT16 File_Creation_Year;                                   // 2 Bytes
    UINT16 Header_Size;                                          // 2 Bytes
    ULONG32 Offset_to_point_data;                                // 4 Bytes
    ULONG32 Number_of_Variable_Length_Records;                   // 4 Bytes
    CHAR Point_Data_Format_ID;                                   // 1 Bytes
    UINT16 Point_Data_Record_Length;                             // 2 Bytes
    ULONG32 Number_of_Point_records;                             // 4 Bytes 
    ULONG32 Number_of_points_by_return[5];                       // 20 Bytes / Verified

    double X_Scale_Factor;                                       // 8 bytes  / Verified
    double Y_Scale_Factor;                                       // 8 bytes
    double Z_Scale_Factor;                                       // 8 bytes
    double X_Offset;                                             // 8 bytes
    double Y_Offset;                                             // 8 bytes
    double Z_Offset;                                             // 8 bytes
    double Max_X;                                                // 8 bytes
    double Min_X;                                                // 8 bytes
    double Max_Y;                                                // 8 bytes
    double Min_Y;                                                // 8 bytes
    double Max_Z;                                                // 8 bytes
    double Min_Z;                                                // 8 bytes

    #ifdef FULLWAVE
        unsigned long long Start_of_Waveform_Data_Packet_Record; // 8 bytes
    #endif

    union
    {
        char* MemoryBlock;
    };

} *header;

struct PointRecord4
{
    UINT32 X;
    UINT32 Y;
    UINT32 Z;
    UINT16 Intensity;
    CHAR BitMask;
    CHAR Classification;
    CHAR ScanAngleRank;
    CHAR UserData;
    UINT16 PointSourceID;
    double GPSTime;
    CHAR WPDI;
    UINT64 WFOffset;
    UINT32 WFPacketSize;
    float WFReturnLocation;
    float WFXt;
    float WFYt;
    float WFZt;
};

extern header ptr = new LasHeader;

HRESULT OpenLasFile(char *path)
{
    HRESULT result;
    ifstream input_file(path, ios::in | ios::binary);
    result = GetLastError();

    input_file.read(PTR(ptr), sizeof(LasHeader));
    result = GetLastError();
    input_file.seekg (ptr->Offset_to_point_data, input_file.beg);

    PointRecord4 * AllRegisters = new PointRecord4[ptr->Number_of_Point_records];

    if (ptr->Point_Data_Format_ID == 4)
        switch ((*ptr).Point_Data_Format_ID)
        {
        case 4:
            {
                PointRecord4 registers[4096];
                ULONG32 pointsToRead = 4096;
                ULONG32 pointsLoaded = 0;               
                ULONG32 i;

                for (i = 0; pointsLoaded < ptr->Number_of_Point_records; i += pointsToRead)
                {
                    pointsToRead =  std::min(pointsToRead, ptr->Number_of_Point_records - pointsLoaded);
                    input_file.read(PTR(&registers), sizeof(PointRecord4) * pointsToRead);
                    pointsLoaded += pointsToRead;

                    //Insert registers[4096] into AllRegisters, Appending it
                } 
            } break;
    }

    input_file.close();

    return result;
}
4

2 回答 2

0

对于您的特殊情况,您可以通过读入目标缓冲区来保存副本:

input_file.read(AllRegisters + pointsLoaded, sizeof(PointRecord4) * pointsToRead);

在其他需要复制的情况下,memcpy 是复制大量 POD 数据的最佳选择。

于 2013-11-05T01:47:36.247 回答
0

目前尚不清楚为什么您不只是直接阅读AllRegisters.

但是,我怀疑附加阶段不是瓶颈。当您像这样读取大块数据时,使用无缓冲 I/O 是值得的。磁盘 I/O 将是您的限制因素,而不是内存 I/O。

请参阅我关于C 中缓冲非缓冲 I/O 的帖子。

这是一篇关于无缓冲 I/O 的文章std::ifstream

于 2013-11-05T01:51:21.663 回答