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に関するの投稿を参照してください。

これは、バッファリングされていない I/O を扱った投稿です。std::ifstream

于 2013-11-05T01:51:21.663 に答える