簡體   English   中英

std :: sort在指針容器上

[英]std::sort on container of pointers

我想探討在新分配的結構(或類)的向量中對數據進行多次解引用時的性能差異。

struct Foo
{
    int val;
    // some variables
}

std::vector<Foo*> vectorOfFoo;

// Foo objects are new-ed and pushed in vectorOfFoo
for (int i=0; i<N; i++)
{
   Foo *f = new Foo;
   vectorOfFoo.push_back(f);
}

在我遍歷向量的代碼部分中,我想通過許多迭代器取消引用來增強引用的局部性,例如,我經常執行雙重嵌套循環

for (vector<Foo*>::iterator iter1 = vectorOfFoo.begin(); iter!=vectorOfFoo.end(); ++iter1)
{
   int somevalue  = (*iter)->value;

}

顯然,如果vectorOfFoo內部的指針距離很遠,我認為引用的位置有些丟失。

如果在循環之前在對向量進行迭代之前對其進行排序,那么性能會如何? 在重復進行引用時是否應該有更好的性能?

我是否確保連續的“ new”分配在內存布局中接近的指針?

只是回答您的最后一個問題:不,沒有保證,無論new在哪里分配內存。 分配可以分布在整個內存中。 根據內存的當前碎片,您可能會幸運地發現它們有時彼此靠近,但不能保證-或實際上不能保證。

如果要改善對象的引用局部性,則應考慮“池分配”。

但是,如果不進行分析,那是沒有意義的。

這取決於許多因素。

首先,它取決於如何從向量指向的對象進行分配。 如果將它們分配在不同的頁面上,那么您將無濟於事,只能修復分配部分和/或嘗試使用軟件預取。

通常,您可以檢查malloc給出了哪些虛擬地址,但是作為較大程序的一部分,單獨分配的結果是不確定的。 因此,如果您想控制分配,則必須更加智能。

如果是NUMA系統,則必須確保正在訪問的內存是從運行進程的節點的物理內存中分配的。 否則,無論您做什么,內存都將來自另一個節點,並且在這種情況下您將無法執行任何操作,除非將程序轉移回其“ home”節點。

您必須檢查從一個對象跳到另一個對象所需的步幅。 預取器可以識別512字節窗口內的步幅。 如果跨度更大,則是從預取程序的角度談論隨機內存訪問。 然后它將關閉,以免從緩存中刪除您的數據,並且在那里您能做的最好的事情就是嘗試使用軟件預取。 這可能會或可能不會有幫助(始終進行測試)。

因此,如果對指針的向量進行排序使它們所指向的對象以相對較小的步幅連續放置在一起-那么,是的,您可以通過使其對預取硬件更加友好來提高內存訪問速度。

您還必須確保對向量進行排序不會導致較差的增益/損耗比。

附帶說明一下,根據使用每個元素的方式,您可能希望一次分配所有元素和/或將這些對象拆分為不同的較小結構,然后遍歷較小的數據塊。

無論如何,您絕對必須在更改前后測量整個應用程序的性能。 這種優化是一項棘手的業務,即使從理論上講應該提高性能,但情況可能會變得更糟。 有許多工具可用於幫助您配置內存訪問。 例如,cachegrind。 英特爾的VTune也是如此。 和許多其他工具。 因此,請勿猜測,嘗試和驗證結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM