найти против равных и производительности

Я провожу некоторые тесты с помощью find, equal_range и моих собственных функций бинарного поиска, и у меня возникают проблемы с пониманием того, почему equal_range занимает так много времени по сравнению с 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 << " found\n";
else
cout << look << " not found\n" ;
}
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 << " found\n";
else
cout << look << " not found\n" ;
}

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 << " found\n";
else
cout << look << " not found\n" ;
}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 << " found\n";
else
cout << look << " not found\n" ;
}

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

ура

1

Решение

В отладочной сборке в 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

Проверка итератора в отладочной сборке сильно замедлит его.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]