2

大規模なデータセットを読み取り、必要な方法でフォーマットしてから、別のファイルに書き込もうとしています。速度を向上させるために、SAS または STATA よりも C++ を使用しようとしています。通常、データ ファイルは約 10 ギガバイトです。そして、私の現在のコードは実行に 1 時間以上かかります (そして、私のコードでは何かが非常に非効率的であると確信しているので、それを終了します。

これを行うより効率的な方法はありますか?ファイルをメモリに読み込んで、switch ステートメントを使用して分析することはできますか? (私は32GBのRAM Linux 64ビットを持っています)。ループ内で読み取りと書き込みを行うと、常に読み取りと書き込みが行われるため、速度が低下する可能性はありますか? これを高速化するために、あるドライブから読み取ってから別のドライブに書き込もうとしました。

スイッチケースはそれを遅くしていますか?

このプロセスでは、getline を使用してデータを読み取り、switch ステートメントを使用してデータを正しく解析し、outfile に書き込みます。そして、3億行繰り返します。switch ステートメントにはさらに 10 のケースがありますが、簡潔にするためにコピーしませんでした。

コードはすべてメイン関数に含まれているため、おそらく非常に醜いですが、魅力に取り組む前にそれを機能させたかったのです。

read() を使用してみましたが、成功しませんでした。何か明確にする必要がある場合はお知らせください。

お手伝いありがとう!

 #include <iostream>
 #include <fstream>
 #include <string>
 #include <sstream>
 #include <stdio.h>
 //#include <cstring>
 //#include <boost/algorithm/string.hpp>

 #include <vector>

  using namespace std;
 //using namespace boost;


 struct dataline
{
char type[0];
double second;
short mill;
char event[1];
char ticker[6];
char marketCategory[1];
char financialStatus[1];
int roundLotSize;
short roundLotOnly;
char tradingState[1];
char reserved[1];
char reason[4];
char mpid[4];
char primaryMarketMaker[1];
char primaryMarketMode[1];
char marketParticipantState[1];
unsigned long orderNumber;
char buySell[0];
double shares;
float price;
int executedShares;
double matchNumber;
char printable[1];
double executionPrice;
int canceledShares;
double sharesBig;
double crossPrice;
char crossType[0];
double pairedShares;
double imbalanceShares;
char imbalanceDirection[1];
double fairPrice;
double nearPrice;
double currentReferencePrice;
char priceVariationIndicator[1];
};

  int main () 
{
string a; 
string b;
string c;
string d;
string e;
string f;
string g;
string h;
string k;
string l;
string times;
string smalltimes;

short time;     //counter to keep second filled
short smalltime;    //counter to keep millisecond filled
double N;
double NN;
double NNN;
int length;
char M; 
//vector<> fout;
string line;

ofstream fout ("/media/3tb/test.txt");
ifstream myfile;
myfile.open("S050508-v3.txt");

dataline oneline;

if (myfile.is_open())
    {
    while ( myfile.good() )
        {
        getline (myfile,line);
//      cout << line<<endl;;

        a=line.substr(0,1);
        stringstream ss(a);
        char type;
        ss>>type;


        switch (type)
            { 
            case 'T':
                {
                if (type == 'T')
                    {
                    times=line.substr(1,5);
                    stringstream s(times);
                    s>>time;
                    //oneline.second=time;
                    //oneline.second;
                    //cout<<time<<endl;
                    }
                else
                    {
                    time=time;
                    }
                break;
                }
            case 'M':
                {
                if (type == 'M')
                    {
                    smalltimes=line.substr(1,3);
                    stringstream ss(smalltimes);
                    ss>>smalltime;      //oneline.mill;
                //  cout<<smalltime<<endl;                            //smalltime=oneline.mill;
                    }
                else
                    {
                    smalltime=smalltime;
                    }
                break;
                }


            case 'R':
                {
                oneline.second=time;
                oneline.mill=smalltime;

                a=line.substr(0,1);
                stringstream ss(a);
                ss>>oneline.type;

                b=line.substr(1,6);
                stringstream sss(b);
                sss>>oneline.ticker;

                c=line.substr(7,1);
                stringstream ssss(c);
                ssss>>oneline.marketCategory;

                d=line.substr(8,1);
                stringstream sssss(d);
                sssss>>oneline.financialStatus;

                e=line.substr(9,6);
                stringstream ssssss(e);
                ssssss>>oneline.roundLotSize;

                f=line.substr(15,1);
                stringstream sssssss(f);
                sssssss>>oneline.roundLotOnly;

                *oneline.tradingState=0;
                *oneline.reserved=0;
                *oneline.reason=0;
                *oneline.mpid=0;
                *oneline.primaryMarketMaker=0;
                *oneline.primaryMarketMode=0;
                *oneline.marketParticipantState=0;
                oneline.orderNumber=0;
                *oneline.buySell=0;
                oneline.shares=0;
                oneline.price=0;
                oneline.executedShares=0;
                oneline.matchNumber=0;
                *oneline.printable=0;
                oneline.executionPrice=0;
                oneline.canceledShares=0;
                oneline.sharesBig=0;
                oneline.crossPrice=0;
                *oneline.crossType=0;
                oneline.pairedShares=0;
                oneline.imbalanceShares=0;
                *oneline.imbalanceDirection=0;
                oneline.fairPrice=0;
                oneline.nearPrice=0;
                oneline.currentReferencePrice=0;
                *oneline.priceVariationIndicator=0;

                break;
                }//End Case 
            }//End Switch
            }//end While
    myfile.close();

     }//End If
else cout << "Unable to open file"; 
cout<<"Junk"<<endl;

return 0;
}

更新だから私はメモリマップを使用しようとしてきましたが、今ではセグメンテーション違反が発生しています。私はさまざまな例に従って、自分に合ったものをつなぎ合わせようとしています。セグメンテーション違反が発生するのはなぜですか? コードの最初の部分は次のようになります。

int main (int argc, char** path) 
 {
 long i;
 int fd;
 char *map;
 char *FILEPATH = path;
 unsigned long FILESIZE;
 FILE* fp = fopen(FILEPATH, "/home/brian/Desktop/S050508-v3.txt");
 fseek(fp, 0, SEEK_END);
 FILESIZE = ftell(fp);
 fseek(fp, 0, SEEK_SET);
 fclose(fp);
 fd = open(FILEPATH, O_RDONLY);

 map = (char *) mmap(0, FILESIZE, PROT_READ, MAP_SHARED, fd, 0);

 char z;
 stringstream ss;

 for (long i = 0; i <= FILESIZE; ++i) 
    {
    z = map[i];
    if (z != '\n') 
        {
        ss << z;
            }
    else 
        {
            // c style tokenizing
            ss.str("");
            }
        }
 if (munmap(map, FILESIZE) == -1) perror("Error un-mmapping the file");
 close(fd);
4

1 に答える 1

1

通常、データ ファイルは約 10 ギガバイトです。... スイッチのケースが原因で速度が低下していませんか?

ほとんど間違いなく、I/O バウンドのようなにおいがします。しかし、それを測定することを検討する必要があります。最新の CPU にはパフォーマンス カウンターがあり、適切なツールを使用すると非常に簡単に活用できます。しかし、問題をいくつかの主要な領域 (デバイスへの I/O、メモリへのロード/ストア、CPU) に分割することから始めましょう。各操作にかかる時間を理解するために、クロックを読み取るコード内にいくつかのマーカーを配置できます。または命令をlinux使用して、OS ティックよりも精度の高いクロックにアクセスできます。clock_gettime()rdtsc

mmap/を検討CreateFileMappingしてください。アクセスしているページの効率/スループットが向上する可能性があります。

すでにページインされている大量のデータをストリーミングする場合は、ラージ/ヒュージ ページを検討してください。

マニュアルからmmap()

説明

mmap() は、呼び出しプロセスの仮想アドレス空間に新しいマッピングを作成します。新しいマッピングの開始アドレスは、addr で指定されます。length 引数は、マッピングの長さを指定します。

例をmmap()次に示します。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#define FILEPATH "/tmp/mmapped.bin"
#define NUMINTS  (1000)
#define FILESIZE (NUMINTS * sizeof(int))

int main(int argc, char *argv[])
{
    int i;
    int fd;
    int *map;  /* mmapped array of int's */

    fd = open(FILEPATH, O_RDONLY);
    if (fd == -1) {
    perror("Error opening file for reading");
    exit(EXIT_FAILURE);
    }

    map = mmap(0, FILESIZE, PROT_READ, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
    }

    /* Read the file int-by-int from the mmap
     */
    for (i = 1; i <=NUMINTS; ++i) {
    printf("%d: %d\n", i, map[i]);
    }

    if (munmap(map, FILESIZE) == -1) {
    perror("Error un-mmapping the file");
    }
    close(fd);
    return 0;
}
于 2013-02-09T02:58:43.030 に答える