2017-11-04 22 views
1

마치 마침내 약간의지도 삽입 속도 (삽입하기 전에 정렬)를 개선 한 것처럼 보입니다. 이 결과에 대해 어떻게 생각하십니까? 더 이상 최적화가 있습니까?지도 삽입 속도를 높이는 방법은 무엇입니까?

#include <map> 
#include <iostream> 
#include <algorithm> 

int main (int argc, char* argv []) { 
    //a map<size_t, size_t> random initilisation 
    std::map<size_t, size_t> m0, m1; 
    { 
    std::vector<std::pair<size_t, size_t> > t (10000, std::pair<size_t, size_t> ((size_t) -1, (size_t) -1)); 
    std::vector<std::pair<size_t, size_t> >::iterator i (t.begin()); 
    for (; i != t.end(); ++i) { 
     i->first = rand() % 1000000; 
     i->second = rand() %1; 
    } 
    m0.insert (t.begin(), t.end()); 
    m1 = m0; 
    } 
    //vins : 
    std::vector<std::pair<size_t, size_t> > vins (10000, std::pair<size_t, size_t> (0, 0)); 
    { 
    std::vector<std::pair<size_t, size_t> >::iterator i (vins.begin()); 
    for (; i != vins.end(); ++i) { 
     i->first = rand() % 1000000; 
     i->second = rand() %1; 
    } 
    } 
    //normal insertion 
    clock_t t0 (clock()), t1 (t0); 
    { 
    m0.insert (vins.begin(), vins.end()); 
    } 
    t1 = clock(); 
    std::cout << "normal insertion took " << (size_t) (t1 - t0) << " ticks" << std::endl; 
    //sort + hint insertion 
    t0 = t1; 
    { 
    std::sort (vins.begin(), vins.end(), [] (std::pair<size_t, size_t>& p0, std::pair<size_t, size_t>& p1)->bool { 
     return (p0.first < p1.first ? true:false); 
    }); 
    std::map<size_t, size_t>::iterator ihint (m1.begin()); 
    //std::vector<std::pair<size_t, size_t> >::iterator i (vins.begin()); 
    //imroved and more C++11 solution 
    std::for_each (vins.begin(), vins.end(), [&ihint, &m1] (std::pair<size_t, size_t>& p) { 
     ihint = m1.insert (ihint, p); 
    }); 
    } 
    t1 = clock(); 
    std::cout << "insertion after sorting took " << (size_t) (t1 - t0) << " ticks" << std::endl; 
    if (m0 != m1) std::cout << "but insertion is nok" << std::endl; 
    else std::cout << "and insertion is ok" << std::endl; 
} 

레노버의 결과는 센터 생각 :

정렬 한 후 삽입 (1706)했다

틱하고 그렇지 않으면 삽입

+0

을 다음'표준 : unordered_map도 '더 빠를 수도 있습니다. 또한 컴파일러 최적화가 켜져 있는지 확인하십시오 (보통'-O2' 또는'-O3'). 내 컴퓨터에서 정상적인 힌트 삽입에 대해 이러한 향상된 성능을 3 배로 사용하여 두 번째 결과에서 몇 백 개 틱을 두드렸다. 마지막으로 [codereview] (https://codereview.stackexchange.com/)에 더 적합 할 수 있습니다. – hnefatl

+0

나는 고속도로를 사용 중이다. 그러나 표준 std :: unordered_map보다 map이 더 낫다고 믿었다. 내가 잘못 ? –

+0

@hnefatl 형식이 모호한 제 질문 이었기 때문에 제 의견을 삭제했습니다. 이 맵을 더 빠르게 만들 수있는 컴파일러 최적화가 있다면 주로 관심이있었습니다. 그래서'std :: unordered_map'을 이미 사용하고 있다면 가능한 컴파일러 최적화를 사용하여 더 빠르게 만들 수 있습니까? –

답변

1

괜찮 2355했다 삽입 항목을 주문해야합니다. std::unordered_map을 사용하는 것이 일반적으로 std::map보다 좋습니다. 바 대신 해시 테이블을 사용합니다. 대부분의 구현에서 lanced tree는 작업이 O(log n)이 아니라 평균 O(1)임을 의미합니다. 또한 기본 데이터 구조 (배열)가 일반적으로 트리보다 캐시 친화적이기 때문에 캐시 위치에서 성능이 향상 될 수 있습니다. -O3 (또는 이와 유사한 최적화 수준)을 사용

당신의 코드의 성능을 향상하지만, /지도의 삽입의 성능에 영향을 (아직 컴파일 된 것 같은) 작업을 찾을 가능성이 있습니다. -Ofast을 사용하면 컴파일러가 더 이상 엄격하게 표준을 준수 할 필요가 없다는 것을 명심하십시오. 성능이 중요하고 코드가 예상대로 작동하는지 확인하는 데 사용하지만 대개는 -O3입니다. 충분히. 내 컴퓨터에


(데비안, g ++ 6.3.0), 몇 가지 실행을 사용하고 거친 평균 복용 : 당신이 주문 속성을 필요로하지 않는 경우

Configuration    Normal Hint Insertion Hint Insertion 
------------------------- ----------------------- ---------------- 
    std::map,   -O0     9750    9200 
    std::map,   -O3     8000    4250 
    std::unordered_map, -O0     7000    9700 
    std::unordered_map, -O3     4200    5000 
+0

그래서 정렬되지 않은 맵 보통 삽입 (4200)은 노멀 맵 (4250)에 힌트 삽입보다 약간 낫습니다. –

+0

@ Saint-Martin Yep, 내 컴퓨터에서 - 힌트 삽입 작업은 삽입에 오버 헤드를 추가하지만 삽입 자체의 속도를 높이는데 도움이되지 않는다고 생각합니다. 힌트 삽입에서 데이터를 정렬하고'std :: unordered_map'이 정렬되지 않았으므로 전혀 도움이되지 않습니다. – hnefatl

+0

@ Saint-Martin 게시물에 귀하의 질문에 답변이있는 경우 [대답으로 표시] (https://stackoverflow.com/help/someone-answers)를 고려하십시오. – hnefatl