2012-10-15 34 views
0

我很新的C++編程世界的,對不起,我amatuerish問題:有沒有快速內存訪問的技巧?

我獲取存儲在主存儲器(1-d陣列)的數據塊大,我需要訪問一些數據經常有,我這樣做的方式是:

float *x=new float[20];//array to store x; 
int *indlistforx=new int[20];//array to store the index of x; 
float *databank=new float[100000000];//a huge array to store data 

/... fill data to databank.../ 


for (int i=0;i<N;i++)//where N is a very large number; 
{ 
    /... write index to indlistforx.../ 
    getdatafromdatabank(x, indlistforx, databank); 
    //Based on the index provided by indlistforx, read data from databank then pass them to x 

    /...do something with x.../ 
    }; 

是否有訪問這些數據的有效/快速的方式(x的指數是不對齊的,它是不可能被排列)?

非常感謝提前!

+2

'new float [100000000];'?可能你住在70年代... – 2012-10-15 21:58:21

+2

我不太明白你的問題。你的代碼的某些部分運行速度太慢了嗎? –

+0

我不明白這個問題。什麼是'x'? – Claudix

回答

2

由於浮法需要初始化,你真的應該用std :: vector的<>,它不是慢,構造和填充像這樣:

std::vector<float> databank(100000000, 0.0f); 

有用於高速化的幾個選項:

1)如果有一個合理的大鍵(索引)重用,那麼你可以使用某種緩存或記憶策略。例如, 參見http://www.boost.org/doc/libs/1_51_0/libs/flyweight/doc/index.html

2)你可以使用std :: async()將處理分成多個線程。

3)確保你的編譯器有SIMD指令(x86上的sse)打開並使用它們。如果不通過使用編譯器內在函數強制使用simd。這將允許接近4倍的改善。

+0

非常感謝,我會嘗試你的建議,至於SIMD,是的,我的程序是用AVX選項編譯的。 – user0002128

+1

我不會downvote,但這個答案本質上是不正確的。切換到矢量不會有幫助。 'std :: vector '和'float *'之間的唯一區別是安全。速度? No. Vectors只是一個原始指針周圍的RAII安全包裝。罪魁禍首是隨機訪問;切換到矢量不會改變這一點。什麼將改變,就是擺脫隨機訪問。 –

3

你還沒有真正顯示你如何訪問您的數據庫,所以這是大家很投機:

  • indlistforx 20個指數到數據庫的清單,讓你做20個隨機訪問?

    • 這些指標的進展如何:它們是連續的還是緊密的,還是隨機的?
    • ,如果他們連續或併攏,將它們分類可以幫助(所以你按升序提高預取讀,分組從同一緩存行的讀取一起)
  • 做了多少不同20個指數羣組跳躍?它們可以重疊嗎?

    • ,如果他們不能重疊,所以你的數據庫被有效分割成一些塊大小,然後處理不同的處理器上的每個分區可以增加有效的緩存可以使用(如果您有多個處理器)
    • 如果請求可以重疊同時運行它們,如果數據庫是隻讀的,仍然可以工作。如果有什麼寫入數據庫,這將成爲高速緩存抖動
  • 您可以在更高層次上得到更好的緩存行爲重新排序的訪問配方:多個順序,更好的參考空間或時間局部性?

    • 這是基本相同,我的第一個建議,而是一個indlistforx請求的級別
    • 以上類似地,可以考慮重新安排他們有效地分割數據庫,並嘗試在多處理器的想法

沒有看到所有的代碼(或有代表性的樣本,我的理解甚至可能太大)很難進入任何更多的細節。

但是,有一種通用技術可能可行......它也可能如此重量級,以至於執行成本超過了節省。

  • 讓你getfromdatabank回到未來/諾/不管,而不是完成同步(或20個期貨載體,如果這不是太細粒度)
  • 嘗試派遣大量的這些並行異步請求,無論是在單獨的線程(訪問期貨將是一個阻塞操作),或使用事件循環來處理完成,像明確的協同例程
  • 有一個專用線程聚集所有數據庫從多個請求訪問,並重新排序獲得更好的緩存性能

只有當額外的同步開銷受改進的讀取性能支配時,以及是否可以有效地並行運行多個查詢時,這纔可以工作。

+0

+1。這種隨機訪問是真正的罪魁禍首。 –

+0

謝謝,就我而言,它是隨機訪問的數據,但沒有重疊。 – user0002128

+0

非常感謝您的建議,是的,我無法發佈代碼的原因是因爲我廣泛使用simd內部函數和CUDA代碼,所以代碼太長,大部分代碼與隨機內存訪問無關。 – user0002128

1

問題不在於你如何表示你的databank。問題在於你如何使用它。在短時間內隨機訪問您的databank廣泛分離的部分將會導致您的性能下降。您的getdatafromdatabank(x, indlistforx, databank)indlistforx幾乎可以保證糟糕的表現。由該indlistforx啓用的隨機訪問帶來顯着的性能損失。如果隨機訪問是絕對必要的,因爲使用您的databank的算法的工作方式如此,這只是您必須付出的代價。

如果您可以修改算法,以便他們可以訪問您的databank中連續的內存塊,那麼您將獲得更好的性能。更改getdatafromdatabank,以便僅指定第一個索引(要加載到x[0]中的元素的索引),而不是數組20索引。

x的大小是否有20?如果您僅僅將輸出x陣列和databank的相關塊保留在1級緩存中,您將獲得最佳性能。如果x的尺寸增加超出此最佳尺寸,性能將開始下降,並可能顯着下降。

+0

我必須使用隨機訪問,我可以重新安排數據庫以允許基於塊的訪問,但是這會降低代碼的其他部分的性能,並且折衷不是很漂亮(實際上我有這個確切原因讓它隨機訪問數據庫是爲了讓我的代碼的其他部分能夠「大塊地」訪問數據),這就是爲什麼我必須堅持隨機訪問大塊數據,我只想知道是否有任何數據提高隨機訪問性能的方法,我想知道多線程是否會有很大幫助? – user0002128