find vs equal_range and performance

find vs equal_range and performance

本文关键字:and performance range vs equal find      更新时间:2023-10-16

我正在用find、equal_range和我自己的二进制搜索函数进行一些测试,我很难理解为什么equal_rrange与find相比需要这么长时间。

我有一个排序的向量,我对搜索操作的持续时间进行计时。最初的想法是看看find和equal_range之间的性能差异,但我预计随着数据量的增长,在向量上迭代会比二进制搜索更糟糕,但这并没有发生。

我的代码很简单,但我"怀疑"这里出了问题,我不知道是什么。

--编辑-我在VS2012中进行这些测试-

        #include "stdafx.h"
        #include <vector>
        #include <algorithm>
        #include <chrono>
        #include <iostream>
        #include <list>
        using namespace std;
        #define TIMING
        #ifdef TIMING
        #define INIT_TIMER auto start = std::chrono::high_resolution_clock::now();
        #define START_TIMER  start = std::chrono::high_resolution_clock::now();
        #define STOP_TIMER(name)  std::cout << name << ": " << 
            std::chrono::duration_cast<std::chrono::nanoseconds>( 
            std::chrono::high_resolution_clock::now()-start 
            ).count() << " ns " << std::endl; 
        #else
        #define INIT_TIMER
        #define START_TIMER
        #define STOP_TIMER(name)
        #endif
        template<typename T> int mybsearch(const std::vector<T>& vec, unsigned start, unsigned end, const T& key)
        {
            // Termination condition: start index greater than end index
            if(start > end)
            {
                return -1;
            }
            // Find the middle element of the vector and use that for splitting
            // the array into two pieces.
            unsigned middle = start + ((end - start) / 2);
            if(vec[middle] == key)
            {
                return middle;
            }
            else if(vec[middle] > key)
            {
                return mybsearch(vec, start, middle - 1, key);
            }
            return mybsearch(vec, middle + 1, end, key);
        }
        template<typename Iterator, typename T> Iterator Tbsearch(Iterator& begin, Iterator& end, const T& key)
        {
            // Keep halving the search space until we reach the end of the vector
            Iterator NotFound = end;
            while(begin < end)
            {
                // Find the median value between the iterators
                Iterator Middle = begin + (std::distance(begin, end) / 2);
                // Re-adjust the iterators based on the median value
                if(*Middle == key)
                {
                    return Middle;
                }
                else if(*Middle > key)
                {
                    end = Middle;
                }
                else
                {
                    begin = Middle + 1;
                }
            }
            return NotFound;
        }
        int _tmain(int argc, _TCHAR* argv[])
        {
            vector<int> V;
            typedef vector<int>::iterator it;
            std::pair<it,it> res;
            it val;
            list<int> L;
            typedef list<int>::iterator itL;
            std::pair<itL,itL> lpair;
            itL lval;
            for(int i=0; i<1000000; i++)
            {
                V.push_back(i+1);
                L.push_back(i+1);
            }
            INIT_TIMER
            cout << "-- find --n";
            for(int k=0;k<10;k++)
            {
                int look = pow(k,k);
                START_TIMER
                val = std::find(V.begin(),V.end(),look);
                STOP_TIMER("find took ")
                if(val!=V.end())
                    cout << look << " foundn";
                else
                    cout << look << " not foundn" ;
            }
            cout << "-- homemade bsearch (index) --n";
            for(int k=0;k<10;k++)
            {
                int look = pow(k,k);
                START_TIMER
                int a = mybsearch(V, 0, V.size()-1, look);
                STOP_TIMER("find took ")
                if(a>0)
                    cout << look << " foundn";
                else
                    cout << look << " not foundn" ;
            }
            cout << "-- homemade bsearch (iterators) --n";
            for(int k=0;k<10;k++)
            {
                int look = pow(k,k);
                START_TIMER
                it f = Tbsearch(V.begin(), V.end(), look);
                STOP_TIMER("find took ")
                if(f!=V.end())
                    cout << look << " foundn";
                else
                    cout << look << " not foundn" ;
            }

            cout << "-- equal range --n";
            for(int k=0;k<10;k++)
            {
                int look = pow(k,k);
                START_TIMER
                res = std::equal_range(V.begin(),V.end(),look);
                STOP_TIMER("equal_range took ")
                if(res.first!=res.second)
                    cout << look << " foundn";
                else
                    cout << look << " not foundn" ;
            }
            return 0;
        }

这次运行的输出是

    -- find --
    find took : 0 ns
    1 found
    find took : 0 ns
    1 found
    find took : 0 ns
    4 found
    find took : 0 ns
    27 found
    find took : 0 ns
    256 found
    find took : 0 ns
    3125 found
    find took : 0 ns
    46656 found
    find took : 2000200 ns
    823543 found
    find took : 2000200 ns
    16777216 not found
    find took : 2000200 ns
    387420489 not found
    -- homemade bsearch (index) --
    find took : 0 ns
    1 not found
    find took : 0 ns
    1 not found
    find took : 0 ns
    4 found
    find took : 0 ns
    27 found
    find took : 0 ns
    256 found
    find took : 0 ns
    3125 found
    find took : 0 ns
    46656 found
    find took : 0 ns
    823543 found
    find took : 0 ns
    16777216 not found
    find took : 0 ns
    387420489 not found
    -- homemade bsearch (iterators) --
    find took : 0 ns
    1 found
    find took : 0 ns
    1 found
    find took : 0 ns
    4 found
    find took : 0 ns
    27 found
    find took : 0 ns
    256 found
    find took : 0 ns
    3125 found
    find took : 1000100 ns
    46656 found
    find took : 1000100 ns
    823543 found
    find took : 0 ns
    16777216 not found
    find took : 0 ns
    387420489 not found
    -- equal range --
    equal_range took : 683068300 ns
    1 found
    equal_range took : 681068100 ns
    1 found
    equal_range took : 681068100 ns
    4 found
    equal_range took : 679067900 ns
    27 found
    equal_range took : 679067900 ns
    256 found
    equal_range took : 680068000 ns
    3125 found
    equal_range took : 683068300 ns
    46656 found
    equal_range took : 677067700 ns
    823543 found
    equal_range took : 680068000 ns
    16777216 not found
    equal_range took : 678067800 ns
    387420489 not found

干杯

在VS2012的调试构建中,我得到了

-- equal range --
equal_range took : 796079600 ns
1 found
equal_range took : 792079200 ns
1 found
equal_range took : 785078500 ns
4 found
equal_range took : 786078600 ns
27 found
equal_range took : 785078500 ns
256 found
equal_range took : 784078400 ns
3125 found
equal_range took : 785078500 ns
46656 found
equal_range took : 786078600 ns
823543 found
equal_range took : 784078400 ns
16777216 not found
equal_range took : 784078400 ns
387420489 not found

而在一个发布版本中,我得到了

-- equal range --
equal_range took : 0 ns
1 found
equal_range took : 0 ns
1 found
equal_range took : 0 ns
4 found
equal_range took : 0 ns
27 found
equal_range took : 0 ns
256 found
equal_range took : 0 ns
3125 found
equal_range took : 0 ns
46656 found
equal_range took : 0 ns
823543 found
equal_range took : 0 ns
16777216 not found
equal_range took : 0 ns
387420489 not found

调试构建中的迭代器检查会大大降低速度。