[英]Iteration speed of unordered_set vs vector
我有一個應用程序,我需要在其中存儲不同客戶的各種子集。 容器中客戶的順序無關緊要。
由於順序無關緊要,我希望與std::vector<int>
相比,在std::unordered_set<int>
上存儲和迭代這組客戶會更快。
然而, CPPREference指出:
unordered_set 容器比 set 容器更快地通過它們的鍵訪問單個元素,盡管它們通常對於通過其元素的子集進行范圍迭代的效率較低。
為了測試這一點,我評估了迭代std::unoredered_set
和std::vector
所需的時間。
#include <vector>
#include <unordered_set>
#include <chrono>
#include <stdio.h>
static const int NoElements = 100000000;
int main()
{
std::vector<int> VecofElems;
VecofElems.reserve(NoElements);
std::unordered_set<int> SetofElems;
SetofElems.reserve(NoElements);
for (int i = 0; i < NoElements; i++)
VecofElems.push_back(i);
for (int i = 0; i < NoElements; i++)
SetofElems.insert(i);
auto VecIterStartTime = std::chrono::steady_clock::now();
long vec_cumulative_sum = 0;
for (std::vector<int>::const_iterator viter = VecofElems.begin(); viter != VecofElems.end(); ++viter)
vec_cumulative_sum += *viter;
auto VecIterEndTime = std::chrono::steady_clock::now();
std::chrono::duration<double, std::milli> VecTime = VecIterEndTime - VecIterStartTime;
auto SetIterStartTime = std::chrono::steady_clock::now();
long set_cumulative_sum = 0;
for (std::unordered_set<int>::const_iterator uositer = SetofElems.begin(); uositer != SetofElems.end(); ++uositer) {
set_cumulative_sum += *uositer;
}
auto SetIterEndTime = std::chrono::steady_clock::now();
std::chrono::duration<double, std::milli> SetTime = SetIterEndTime - SetIterStartTime;
printf("Vector Sum %ld, Size %ld, Time Taken %f\n", vec_cumulative_sum, VecofElems.size(), VecTime);
printf("Set Sum %ld, Size %ld, Time Taken %f\n", set_cumulative_sum, SetofElems.size(), SetTime);
getchar();
}
我機器上的output,上面在MSVC編譯器的Release Mode下編譯時是:
Vector Sum 887459712, Size 100000000, Time Taken 51.340000
Set Sum 887459712, Size 100000000, Time Taken 4772.139100
表明遍歷向unordered_set
vector
許多數量級。
在我的應用程序中,由於容器中元素的順序無關緊要,並且由於std::vector
保留了順序(在這種情況下是不必要的),因此是否有任何其他容器可以比std::vector
在迭代中更快通過容器的各種元素?
std::vector 是最快的 STL 容器,適用於您的場景中的線性迭代。 這僅僅是因為 memory 是連續分配的,因此可以受益於緩存機制。 向量迭代器只是在內部增加一個指針。
如果可能,您可以嘗試使用比int
更小的類型來進一步提高性能。
在您的情況下,我認為並行化/SIMD 會最大程度地提高性能以減少。 這可以通過自動矢量化來實現(檢查項目編譯器設置)。
您也可以嘗試 OMP 這樣做(未經測試)
size_t end = VecofElems.size();
#pragma omp parallel for shared(vec_cumulative_sum ) reduction(+: vec_cumulative_sum )
for (size_t i = 0; i < end; ++i) {
vec_cumulative_sum += VecofElems[i];
}
這將並行運行多個線程。 因此,將vec_cumulative_sum
聲明為在線程之間共享很重要。
std::for_each
提供了一些簡單的方法來利用並行性,包括矢量化。 這允許像這樣簡單地使用任何 STL 容器,如 std::vector (以及任何其他提供迭代器的容器)
std::for_each(std::execution::par, VecofElems.begin(), VecofElems.end(),
, []() {
// have some fun using a lambda, or function
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.