2012-06-05 6 views
1

얼마 전 검색 알고리즘을 사용하여 몇 가지 벤치 마크를 수행 한 결과, 이전 bsearch()가 std :: binary_search()와 비교해 훨씬 빨랐다는 사실에 깊은 인상을 받았습니다. 나는 괜찮은 컴파일러가 가능하면 bsearch()에 의해 std :: binary_search()를 대체 할 수있을 것이라고 생각했지만, GCC 4.7을 사용하고 있어도 bsearch는 std :: binary_search보다 5 배 빠른 것을 수행하는 것처럼 보입니다.bsearch wrapper

그래서 나는 같은 인터페이스와 std :: binary_search를 사용하여 bsearch 용 일종의 래퍼를 만들려고 시도하는 것이 가장 좋습니다. 그러나 알려지지 않은 이유로, 나는 그것을 할 수 없었습니다. 여기 내 코드 :

template<typename InputIterator, class T> 
bool binary_search(InputIterator first, InputIterator last, const T& value) 
{ 
    auto cmp = [](const void* a, const void* b) 
    { 
     return (int) ((*(T*)a) == (*(T*)b)); 
    }; 

    std::cout << value << std::endl; 
    T* res = (T*) bsearch(&value, first, last-first, sizeof(*first), cmp); 
    return res != nullptr; 
} 

코드가 잘 컴파일되고 실행시 크래시되지 않습니다. 그러나 bsearch는 하나의 내부 반복 (* res가 매개 변수로 전달 된 탭의 중간 값과 항상 동일 함) 직후 중지됩니다. 나는 그것이 효과가없는 이유를 발견 할 수 없다. 가능하다면 약간의 도움이 될 것입니다.

감사합니다. 속도를 확인하는 데 사용되는 코드를 요청하는 사람들을 위해


:

const std::string keyword_str[] = { 
    // Some strings 
}; 

int cmp(const void* s1, const void* s2) 
{ 
    return (int) ((*(std::string*)s1) == (*(std::string*)s2)); 
} 

int main() 
{ 
    time_t start, end; 
    double dif; 
    time (&start); 

    // Code 
    for (const string& str: keyword_str) 
    { 
     for (size_t i = 0 ; i < 1000000 ; ++i) 
     { 
      // std::binary_search (uncomment to check) 
      //bool a = std::binary_search(keyword_str, keyword_str+28, str); 

      // bsearch 
      char** st = (char**) bsearch(&str, keyword_str, 28, sizeof(keyword_str[0]), cmp); 
     } 
    } 

    time (&end); 
    dif = difftime (end, start); 
    printf("Time spent: %fs.\n", dif); 

    return 0; 
} 
+3

이 5 배의 성능 차이를 보여주는 테스트 사례를 보시려면 여기를 클릭하십시오. –

+2

당신이'InputIterator'라고 이름 붙인 것들은'RandomAccessIterator'를 구현할 필요가 있습니다 _concept_ –

+7

'cmp'가 다른 원소들에 대해'(int) false' ('== 0')를 반환하기 때문에 빠릅니다. 'bsearch'는'0'을 보았을 때 'equal'을 의미한다고 생각하고 검색을 멈 춥니 다. 그래서'bsearch'는 보통'std :: binary_search'가 진짜 검색을하는 동안 요소를 아주 빨리 발견했다고 생각합니다. – sth

답변

3

bsearch는 함수 포인터를 받아, cmp는 함수 포인터가 아닙니다. (편집 :cmp은 변수를 포착하지 않으므로 대괄호는 비어 있으며 함수 포인터로 전달할 수 있습니다.이 동작은 C의 §5.1.2/6에 명시되어 있습니다. ++ 11 표준)

bsearch도 비교 함수가 반환 할 것으로 예상되는 올바른 값을 반환하지 않습니다. 키가 배열 요소보다 작은 경우 -1을 반환하고, 동일한 경우 0을, 키가 배열 요소보다 큰 경우 1을 반환합니다. cmp 함수는 부등 값이 같으면 0을 반환하고 동등하면 1을 반환합니다. 따라서 비교하려는 첫 번째 요소가 키와 일치하지 않으면 cmpbsearch이 올바른 요소를 찾았다 고 생각하기 때문에 이들이 같다고 생각하고 bsearch이 멈추게 만듭니다. 일반적

+0

오, 이제 말하겠습니다. bsearch 함수가 얼마나 잘못되었는지 기억합니다. 하지만 cmp 함수의 유형을 알지 못했습니다. 컴파일 오류가 없기 때문에 유형이 올바른 것으로 생각했습니다. – Morwenn

2

은 단지 어떤 반복자 타입 반복자의 범위에서 작동하는 반면 std::binary_search 요소의 연속적인 배열을 검색 할 수 있기 때문에 std::binary_searchbsearch을 구현할 bsearch를 사용하는 것은 불가능하다. 연결된 목록 반복자, deque 반복자 또는 사용자가 만든 일부 사용자 지정 이국적인 반복자 일 수 있습니다. 분명히이 반복자를 검색 할 방법이 없습니다 bsearch