2011-11-11 14 views
2

文脈は最初にC++ fstreamは間違ったデータを出力します

私のプログラムはファイルに記録されたいくつかの並列計算を行います。スレッドはブロック単位でグループ化されています(私はCUDAを使用しています)。ログファイルには、このようにフォーマットされます。

#begin run 
({blockIdx,threadIdx}) {thread_info} 
({blockIdx,threadIdx}) {thread_info} 
... 
#end run 

私は、ログファイルを読み込み、スレッドによって各実行メッセージをソートする必要がある関数を書いてきました。

//------------------------------------------------------------------------------ 
// Comparison struct for log file sorting 
//------------------------------------------------------------------------------ 
typedef struct 
{ 
    bool operator()(const string &rString1 , const string &rString2) 
    { 
     int closeParenthesisLocalition1 = rString1.find_first_of(')'); 
     int closeParenthesisLocalition2 = rString2.find_first_of(')'); 
     int compResult = rString1.compare(0 , closeParenthesisLocalition1 + 2 , rString2 , 0 , closeParenthesisLocalition2 + 2); 
     return (compResult < 0); 
    } 
} comp; 

//------------------------------------------------------------------------------------ 
// Sort the log file. Lines with same prefix (blockIdx,ThreadIdx) will be grouped in file per run. 
//------------------------------------------------------------------------------------ 
void CudaUnitTest::sortFile() 
{ 
    comp comparison; 
    deque<string> threadsPrintfs; 
    ifstream inputFile(m_strInputFile); 
    assert(inputFile.is_open()); 

    //Read whole input file and close it. Saves disk accesses. 
    string strContent((std::istreambuf_iterator<char>(inputFile)), std::istreambuf_iterator<char>()); 
    inputFile.close(); 

    ofstream outputFile(m_strOutputFile); 
    assert(outputFile.is_open()); 

    string strLine; 
    int iBeginRunIdx = -10; //value just to addapt on while loop (to start on [0]) 
    int iBeginRunNewLineOffset = 10; //"idx offset to a new line char in string. Starts with the offset of the string "#begin run\n". 
    int iEndRunIdx; 
    int iLastNewLineIdx; 
    int iNewLineIdx; 

    while((iBeginRunIdx = strContent.find("#begin run\n" , iBeginRunIdx + iBeginRunNewLineOffset)) != string::npos) 
    { 
     iEndRunIdx = strContent.find("#end run\n" , iBeginRunIdx + iBeginRunNewLineOffset); 
     assert(iEndRunIdx != string::npos); 

     iLastNewLineIdx = iBeginRunIdx + iBeginRunNewLineOffset; 
     while((iNewLineIdx = strContent.find("\n" , iLastNewLineIdx + 1)) < iEndRunIdx) 
     { 
      strLine = strContent.substr(iLastNewLineIdx + 1 , iNewLineIdx); 
      if(verifyPrefix(strLine)) 
       threadsPrintfs.push_back(strLine); 
      iLastNewLineIdx = iNewLineIdx; 
     } 

     //sort last run info 
     sort(threadsPrintfs.begin() , threadsPrintfs.end() , comparison); 
     threadsPrintfs.push_front("#begin run\n"); 
     threadsPrintfs.push_back("#end run\n"); 

     //output it 
     for(deque<string>::iterator it = threadsPrintfs.begin() ; it != threadsPrintfs.end() ; ++it) 
     { 
      assert(outputFile.good()); 
      outputFile.write(it->c_str() , it->size()); 
     } 
     outputFile.flush(); 
     threadsPrintfs.clear(); 
    } 

    outputFile.close(); 
} 

問題は、結果のファイルにゴミのデータが多いことです。たとえば、6KBの入力ログファイルで192KBの出力ログが生成されました。出力ファイルに入力ファイルの繰り返しがたくさんあるようです。コードをデバッグするときに、両端キューはソートの前後に正しい値を示しました。私はofstream書き込み自体に何か問題があると思う。

編集:機能が並行して実行されていません。

+2

複数のスレッドが同時に書き込みを行っていますか? –

+8

あなたはあなたのstd :: ofsを保護しますか?ミューテックスを使った呼出し – BatchyX

+4

@Batchyx:私は何を見て、私はあなたがそこにいたのが好きです。 –

答えて

0

最終コードを表示するだけです。 substrの変更点に注目してください。これは、lenghtを受け取っているインデックスの代わりになりました。

//------------------------------------------------------------------------------------ 
// Sort the log file. Lines with same prefix (blockIdx,ThreadIdx) will be grouped in file per run. 
//------------------------------------------------------------------------------------ 
void CudaUnitTest::sortFile() 
{ 
comp comparison; 
deque<string> threadsPrintfs; 
ifstream inputFile(m_strInputFile); 
assert(inputFile.is_open()); 

//Read whole input file and close it. Saves disk accesses. 
string strContent((std::istreambuf_iterator<char>(inputFile)), std::istreambuf_iterator<char>()); 
inputFile.close(); 

ofstream outputFile(m_strOutputFile); 
assert(outputFile.is_open()); 

string strLine; 
int iBeginRunIdx = -10; //value just to addapt on while loop (to start on [0]) 
int iBeginRunNewLineOffset = 10; //"idx offset to a new line char in string. Starts with the offset of the string "#begin run\n". 
int iEndRunIdx; 
int iLastNewLineIdx; 
int iNewLineIdx; 

while((iBeginRunIdx = strContent.find("#begin run\n" , iBeginRunIdx + iBeginRunNewLineOffset)) != string::npos) 
{ 
    iEndRunIdx = strContent.find("#end run\n" , iBeginRunIdx + iBeginRunNewLineOffset); 
    assert(iEndRunIdx != string::npos); 

    iLastNewLineIdx = iBeginRunIdx + iBeginRunNewLineOffset; 
    while((iNewLineIdx = strContent.find("\n" , iLastNewLineIdx + 1)) < iEndRunIdx) 
    { 
     strLine = strContent.substr(iLastNewLineIdx + 1 , iNewLineIdx - iLastNewLineIdx); 
     if(verifyPrefix(strLine)) 
      threadsPrintfs.push_back(strLine); 
     iLastNewLineIdx = iNewLineIdx; 
    } 

    //sort last run info 
    sort(threadsPrintfs.begin() , threadsPrintfs.end() , comparison); 
    threadsPrintfs.push_front("#begin run\n"); 
    threadsPrintfs.push_back("#end run\n"); 

    //output it 
    for(deque<string>::iterator it = threadsPrintfs.begin() ; it != threadsPrintfs.end() ; ++it) 
    { 
     assert(outputFile.good()); 
     outputFile.write(it->c_str() , it->size()); 
    } 
    threadsPrintfs.clear(); 
} 

outputFile.close(); 
} 
関連する問題