2013-07-24 244 views
2

我試圖讀取大的二進制文件LAS這樣二進制文件讀取性能C++

struct format 
{ 
    double X; 
    double Y; 
    double Z; 
    short red; 
    short green; 
    short blue; 
    short alpha; 
    unsigned long intensity 
    // etc. 
} 

std::ifstream stream; 
Point3 GetPoint() 
{ 
    format f; 
    stream.seekg(offset); 
    offset += sizeof(format); 
    stream.Read((char *)f, sizeof(format)); 
    return Point3(f.X, f.Y, f.Z); 
} 

在主要功能:

Point3* points = new Point3[count] 
for (int i = 0; i < count; i++) 
    points[i] = GetPoint(); 

此項操作需要有1800萬點的記錄約116秒。但在LAS工具中,讀取和開始顯示相同數據需要將近15秒的時間。

怎麼可以快7倍然後我的?多線程還是其他的東西?如果我的閱讀功能不好,那麼它會如何惡化7次呢?

我有一些關於內存映射文件的信息。將整個文件加載到內存的速度非常快,但LAS文件可能超過15GB,這是我的內存大小的過大,因此它將加載到虛擬內存。即使我有足夠的內存,我也必須用循環讀取內存映射文件。

有人可以給我一個關於這種情況的幫助嗎?

+1

你只需要映射文件的一部分,而不是全部。 – Twifty

+0

你確定'stream.Read((char *)f,sizeof(format))'會一直給你想要的結果嗎?我認爲format中的成員不必分配連續內存(絕對增加,但不能保證相鄰) – GuLearn

+1

如果不使用內存映射,請使用大型數組讀取大量記錄。讀取的記錄越多,操作的效率就越高。對於每個讀取操作,驅動器必須定位文件中的開始或位置,然後讀取連續的字節。找到驅動器上的文件位置需要時間,並等待驅動器達到正確的速度。 –

回答

1

根據您的實施ifstream是臭名昭着的緩慢。例如,在MS編譯器上,它依靠<cstdio>進行緩衝。這意味着它爲每個要讀取的字節調用'c'函數。

另外,你確定你可以將內存複製到你的結構中嗎?你有沒有考慮填充?

就像你的問題所述,內存映射文件速度要快很多。你不需要映射整個文件,你可以映射它的一小部分。通常,映射與系統頁面大小相同大小的部分已足夠。

調查mmap

+0

我將盡快進行更多關於mmap的搜索並返回。 –

2

由於該文件正在順序讀取,爲什麼呼叫seekg? 嘗試移除seekg。

一些其他的東西,你可以嘗試:

  • 讀取塊(32K)的文件,並通過這些給另一個線程(尋找生產者/消費者模式)。第二個線程(消費者)可以解析塊並在第一個線程(生產者)等待I/O時填充點數組。
  • 如果Point3定義了一個構造函數,請使用向量<>而不是在創建數組時創建'count'Point3對象。

另外,您如何知道LAS工具等待整個文件在渲染之前被讀取?是否有可能在文件完全讀入之前開始渲染?

+0

其實它正在閱讀特定的索引,你是對的,現在不需要使用它。我認爲這不會有很大的改變?我錯了嗎? –

+0

哇,我很驚訝。現在大約需要62秒。謝謝。 –

+0

@CahitBurakKüçüksütcü如果答案解決了您的問題,您應該通過點擊選中標記確定接受它。 – 0x499602D2