[英]stl map performance?
我正在使用map<MyStruct, I*> map1;
。 顯然,我總應用時間的9%用於那里。 特別是我的一個主要職能的一行。 地圖不是很大(<1k幾乎總是,<20是常見的)。
是否有我可能想要使用的替代實現? 我想我不應該寫自己的,但如果我認為這是一個好主意我可以。
附加信息:我總是在添加元素之前檢查。 如果存在密鑰,我需要報告問題。 在一點之后,我將大量使用地圖進行查找,並且不會再添加任何元素。
首先,您需要了解地圖是什么以及您正在執行的操作代表什么。 std::map
是一個平衡的二叉樹,查找將采用O( log N )
操作,每個操作都是鍵的比較加上一些你可以在大多數情況下忽略的額外操作(指針管理)。 插入大致需要大致相同的時間來定位插入點,加上新節點的分配,實際插入樹和重新平衡。 雖然隱藏的常數更高,但復雜性也是O( log N )
。
當您嘗試在插入之前確定某個鍵是否在地圖中時,會產生查找成本,如果不成功,則定位插入點的成本相同。 你可以通過使用std::map::insert
來避免額外的成本,它返回一個帶有迭代器和bool的對,告訴你插入是否實際發生了或元素是否已經存在。
除此之外,你需要了解它是多么昂貴,比較你的鑰匙,它掉出來什么的問題顯示( MyStruct
可容納只是一個int
或它們的萬),這是你需要考慮的東西。
最后,情況可能是map
不是滿足您需求的最有效的數據結構,您可能需要考慮使用具有預期的恆定時間插入的std::unordered_map
(哈希表)(如果哈希函數是不可怕 )或小數據集甚至純有序陣列(或std::vector
),其上可以使用二進制搜索來定位元件(這將減少分配的數量,在更昂貴的插入物的成本,但是如果持有的類型足夠小,可能值得)
與性能一樣,測量然后嘗試了解花費的時間。 另請注意,在特定功能或數據結構中花費的時間的10%可能很多或幾乎沒有,具體取決於您的應用程序。 例如,如果您的應用程序只是在數據集中執行查找和插入,並且只占CPU的10%,那么您可以在其他任何地方進行優化!
如果密鑰已經存在,可能會更快地執行insert
並檢查pair.second
是否為false
:
像這樣
if ( myMap.insert( make_pair( MyStruct, I* ) ).second == false)
{
// report error
}
else
// inserted new value
...而不是每次都find
一個電話。
您可以嘗試使用散列鍵而不是樹來查找元素的unordered_map
,而不是map
。 這個答案提供了一些提示何時unordered_map
於map
unordered_map
。
這可能是一個長鏡頭,但對於小型集合,有時最關鍵的因素是緩存性能。
由於std::map
實現了一個紅黑樹,它[AFAIK]的緩存效率不高 - 可能將地圖實現為std::vector<pair<MyStruct,I*>>
會是一個好主意,並使用二進制搜索[而不是地圖查找],至少它應該是有效的,一旦你開始只查找[停止插入元素],因為std::vector
更可能適合緩存而不是map
。
這個因子[cpu-cache]通常在大O表示法中被忽略並隱藏為常量,但對於大型集合,它可能會產生重大影響。
您使用地圖的方式是,您在MyStruct
實例的基礎上進行查找,並且根據您的特定實現,所需的比較可能成本也可能不高。
是否有我可能想要使用的替代實現? 我想我不應該寫自己的,但如果我認為這是一個好主意我可以。
如果您能夠很好地理解這個問題,那么您應該詳細說明您的實施將如何更好。
map
是否正確? 如果是這樣,那么您的標准庫的實現可能質量很好(經過優化)。
可以簡化MyStruct
比較嗎?
問題出在哪里 - 調整大小? 抬頭?
您是否最小化了復制並為結構分配成本?
正如評論中所述,如果沒有適當的代碼,幾乎沒有通用的答案可以給你。 但是,如果MyStruct
非常龐大,堆棧復制可能會很昂貴。 也許將指針存儲到MyStruct
並實現自己的比較機制是有意義的:
template <typename T> struct deref_cmp {
bool operator()(std::shared_ptr<T> lhs, std::shared_ptr<T> rhs) const {
return *lhs < *rhs;
}
};
std::map<std::shared_ptr<MyStruct>, I*, deref_cmp<MyStruct>> mymap;
但是,這是您必須要分析的內容。 它可能會加快速度。
你會查找這樣的元素
template <typename T> struct NullDeleter {
void operator()(T const*) const {}
};
// needle being a MyStruct
mymap.find(std::shared_ptr<MyStruct>(&needle,NullDeleter()));
毋庸置疑,優化的潛力更大。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.