2014-01-17 63 views
0

我有一個程序從不同的攝像機獲取原始數據流並將其寫入磁盤。程序運行這些記錄約2分鐘,然後用另一個程序處理幀。在C++中快速寫入很多大文件

每個原始幀都是2MB,幀速率是30fps(即數據速率約爲60MB/s),我正在寫入一個可以輕鬆處理持續> 150MB/s的SSD(通過複製4000 2MB來自另一個磁盤的文件需要38秒,Process Explorer顯示不變的IO活動)。

我的問題是,偶爾會調用fopen()fwrite()fclose()攤位長達5秒,這意味着該幀的300MB建立在內存中作爲備份日誌,並經過幾次這些延遲的,我打的4GB的限制一個32位的進程。 (當延遲發生時,處理資源管理器示出了在IO活動間隙)

有運行在循環調用此函數爲每一個新幀,其被添加到隊列中的線程:

writeFrame(char* data, size_t dataSize, char* filepath) 
{ 
    // Time block 2 
    FILE* pFile = NULL; 
    fopen(&pFile, filepath, "wb"); 
    // End Time block 2 

    // Time block 3 
    fwrite(data,1,dataSize,pFile); 
    // End Time block 3 

    // Time block 4 
    fclose(pFile); 
    // End Time block 4 
} 

(有錯誤檢查也在實際的代碼中,但它對這個問題沒有任何影響) 我正在記錄每個塊所花費的時間以及運行該函數所花費的總時間,並且我得到的結果大部分時間都是像這樣:(times in ms)

TotalT,5,  FOpenT,1,  FWriteT,2, FCloseT,2 
TotalT,4,  FOpenT,1,  FWriteT,1, FCloseT,2 
TotalT,5,  FOpenT,1,  FWriteT,2, FCloseT,2 

即。 〜5ms運行整個功能,〜1ms打開文件,〜2ms調用寫入,〜2ms關閉文件。

偶爾但是(在每50幀平均約1%,但有時也可以是幾千幀的發生這個問題之間),我得到它接管4000ms幀:

TotalT,4032, FOpenT,4023, FWriteT,6, FCloseT,3 

TotalT,1533, FOpenT,1,  FWriteT,2, FCloseT,1530 

所有的幀是相同的大小和它從來沒有fwrite這需要額外的時間,總是fopenfclose

沒有其他進程正在讀取/寫入此SSD(通過進程監視器確認)。

有誰知道什麼可能導致此問題和/或任何避免/緩解此問題的方式?

+0

每個幀都被寫入一個單獨的文件?也許你可以將一組幀寫入單個文件,並有一個單獨的線程進行後處理,以便將之後的N個幀和段分割成單獨的文件(以緩解視頻處理線程中的fopen/fclose調用)。這將允許您的writeFrame func運行得更快,而不會減慢視頻捕獲過程。 – spartygw

+0

考慮檢查'fopen'和'fclose'實際上是否打開和關閉,同時檢查有多少個線程正在運行,這可能是您正在達到最大線程數量。 –

+1

你沒有提到在SSD上使用的平臺或文件系統類型。如果是Windows,這將是一個使用異步寫入的好地方。 – Dan

回答

1

我打算使用X.J.,你可能會把太多的文件寫到一個目錄中。 解決方案可能是爲每批幀創建一個新目錄。另外請考慮在創建文件後直接調用SetEndOfFile,因爲這將幫助Windows在單個操作中分配足夠的空間。

FAT不是一個真正的解決方案,因爲它在大型目錄上做得更糟。

1

準備空文件(2 MB文件填充零)因此,空間已經「準備好」,然後只是覆蓋這些文件。或者創建一個文件,這是一個批量的幾個幀,所以你可以減少文件的數量。

有做的視頻壓縮與解壓縮及播放庫:

libTheora可能是有用的,因爲已經壓縮的幀(以及你將需要輸出在一個單一文件中的視頻),並做到這一點非常快(有損壓縮的方式)。