2010-04-20 27 views
3

我在寫外部合併排序。它的工作方式如下:從大文件中讀取k個塊,在內存中對其進行排序,執行k路合併,完成。所以我需要在k路合併階段從文件的不同部分順序讀取。要做到這一點的最佳方式是:幾個ifstream或一個ifstream並尋求?另外,是否有一個易於異步IO的庫?幾個ifstream與ifstream +不斷尋求

+0

我會爭論fstream _is_一個簡單的異步IO庫:-) – Cameron 2010-04-20 13:07:52

+3

@Cameron除了不是異步 – 2010-04-20 13:18:15

+0

@尼爾:對不起,我是設法混淆異步與隨機訪問。我需要更多的睡眠! – Cameron 2010-04-20 13:24:06

回答

2

在同一個文件上一次使用一個ifstream。不止一個浪費資源,並且您必須反正尋找(因爲默認ifstream的文件指針從文件開頭開始)。

至於C++異步IO庫,請查看this question

編輯:我最初誤解你正在嘗試做什麼(這Wikipedia article填補了我)。我不知道默認情況下有多少ifstream緩衝區,但可以使用pubsetbuf(0, 0);方法described here關閉緩衝區,然後執行自己的緩衝。然而,這可能比使用自動緩衝的多個ifstream慢。有些基準測試是按順序進行的。

+1

你不會「不得不去尋找」,因爲在多個數據流中,你需要爲每個文件塊(k)尋找一個數據流。使用單個流進行多路合併,每合併一個合併(n)大約一次,儘管如果長時間運行的項目來自單個塊,您可能會感到幸運。但是,如果數據最初是隨機排列的,那麼這種可能性可以忽略不計。 – 2010-04-20 13:26:29

1

肯定嘗試多個流。尋找可能會拋出內部緩衝數據(至少在該過程中,即使操作系統將其保留在緩存中),並且如果您正在排序的項目很小,確實可能會非常昂貴。

無論如何,比較兩種fstream策略的性能應該不會太難。做一個k = 2的簡單實驗。

請注意,一個進程可以同時打開的文件數量可能有限制(ulimit -n)。如果達到此目的,則可能需要考慮使用單個數據流,但是要手動緩存來自每個k個數據塊的數據。

如果文件足夠小(相當於:地址空間足夠大),則可能需要使用多個指針來映射文件並使用多個指針。

+0

打開的文件或打開的文件流的數量是否有限制(我只需要訪問1個文件,但是有很多文件流)? 不幸的是文件大小遠遠大於內存大小。外部排序就是這種情況。 – SpyBot 2010-04-20 14:19:10

+0

可能是溪流,但我並不完全確定。當* NIX說「打開文件」時,我認爲這意味着文件描述符的數量,而不是它們指向的不同文件的數量。我提到了mmap,因爲它不需要文件適合內存,只需要給它一個地址範圍(在32或64位虛擬地址空間內)。然後,操作系統執行文件的分段部分進出物理RAM,因爲它們被使用。 – 2010-04-20 15:28:47