簡體   English   中英

unordered_set 與向量的迭代速度

[英]Iteration speed of unordered_set vs vector

我有一個應用程序,我需要在其中存儲不同客戶的各種子集。 容器中客戶的順序無關緊要

由於順序無關緊要,我希望與std::vector<int>相比,在std::unordered_set<int>上存儲和迭代這組客戶會更快。

然而, CPPREference指出:

unordered_set 容器比 set 容器更快地通過它們的鍵訪問單個元素,盡管它們通常對於通過其元素的子集進行范圍迭代的效率較低。

為了測試這一點,我評估了迭代std::unoredered_setstd::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.

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