2016-08-29 53 views
3

這更多的是一個概念性問題。我正在使用的遺留代碼有一個C++線程實現來模擬並行文件讀取。它處理多線程文件讀取的方式是隻將數據塊(比如說2^20 bytes)從文件流式傳輸到char* array,然後多個線程讀取此數組的專用部分。當一個線程完成時,它等待所有其他線程完成(即使用在unique_lock上共享的condition_variable)並完成最後一個線程,將下一個數據塊從文件加載到數組中並繼續該過程,直到整個文件爲止讀。並行閱讀的原因是,這些文件通常超過1 GB,否則非常耗時。加速約爲6x或更多。C++問題多線程文件讀取在虛擬機上運行

我觀察到一些奇怪的行爲。當代碼在物理機器上運行時(即使它是遠程連接的),多線程文件讀取始終正常工作。但是,如果它在虛擬機上運行,​​則有時會在讀取後丟失數據。我已經對每個線程進行了調試,只讀取一行,但有時結果不正確。這表明錯誤結果的原因不是不正確的讀數,而是缺少輸入文件中的整行(一個.txt)。如果增加線程數(線程數越多,失敗次數越多)並增加文件大小(即文件大小大於char* array的大小),則我可以更頻繁地再現錯誤結果。這使我相信這個問題不在多線程文件讀取中,而是與運行時環境(物理與虛擬機)有關。

我只是想大聲想看看是否有人遇到類似的行爲,或者如果有任何見解,爲什麼會出現這種行爲。我正在調查任何buffer overflow問題,但到目前爲止沒有發現任何問題。

編輯:添加關於環境

我使用Visual Studios 2013所以利用MS Visual C++編譯器和所有的物理和虛擬機是Windows Server 2012 R2Windows Server 2008 R264-bitx64-based processors可用的最小內存是32GB更多信息並可能漲至120GB。服務器使用不同版本的Intel Xeon E5 CPU。

+1

是否有可能重現一小段代碼?此外更多的上下文應該有助於回答。什麼平臺是物理機器?什麼是虛擬的?你如何編譯它?嘗試描述兩種環境之間的更多差異 –

+0

@BiagioFesta感謝您的評論。增加了一些更多的細節,但遺留代碼是相互依賴的許多其他功能,並很難重現一個準確的片段。 – kishansudu

回答

3

這幾乎可以肯定意味着你的代碼有一個競爭條件,通常很少發生,但是被你的虛擬機上的條件帶出來。

由於間歇性的可用內核或不同的時間片或甚至從相對自願的改變到更先發制人的任務切換,也許不同的線程調度強調了這個問題。也有可能你錯過了錯誤檢查的地方,也許行閱讀功能有時讀取部分線由於可檢測的IO錯誤,你不檢查,但很少發生在真正的鐵。但是我不能開始調試它,因爲你沒有發佈代碼。

TLDR幾乎可以確定你的代碼是錯誤的,而不是虛擬機的實現(假設它是主流的虛擬機管理程序)。

作爲一個觀點,雖然這與您的問題無關,但我不明白爲什麼您可能以這種方式執行此文件IO,而不是mmap處理文件並讓線程從mmap中讀取。在大多數情況下,這將大大提高效率,並且在大多數操作系統中本質上是線程安全的。

+1

感謝@Vality的一些見解。我也在考慮做一個內存映射實現。該代碼至少已有幾年的歷史,並不完全知道當前設計背後的決定。 – kishansudu

+0

@kishansudu不用擔心,我很高興答案至少有點幫助,我們都必須維護舊的代碼,有時候這麼好的運氣來追蹤問題。 – Vality