초 고성능 C / C ++ 해시 맵 (테이블, 사전) [닫기]


84

고성능 해시 맵 데이터 구조의 값을 구성하기 위해 기본 키 (int, 어쩌면 long)를 매핑해야합니다.

내 프로그램에는 이러한 맵이 수백 개 있으며 각 맵에는 일반적으로 최대 수천 개의 항목이 있습니다. 그러나지도는 지속적으로 "새로 고침"또는 "이탈"합니다. 수백만을 처리 상상 add하고 delete두 번째 메시지.

이 사용 사례에 맞는 데이터 구조를 가진 C 또는 C ++의 라이브러리는 무엇입니까? 또는 자신의 건물을 어떻게 추천 하시겠습니까? 감사!


1
키 검색을 데이터로 처리해야합니까?
Guillaume Lebourgeois

3
업데이트 또는 검색이 더 자주 이루어 지나요? (키를 변경하지 않는 추가 / 삭제 또는 읽기 / 업데이트)
falstro

stackoverflow.com/questions/266206/... . 시작하기에 좋은 곳입니다.
DumbCoder

2
@roe:추가 / 삭제 작업은 가져 오기 작업보다 훨씬 (100 배) 더 자주 발생합니다.
Haywood Jablomey

1
4 년 반 후에 귀하의 요구에 가장 적합한 것이 무엇인지 아는 것은 흥미로울 것입니다. 현재 답변 중 어느 것도 만족스럽지 않은 경우 직접 작성하고 수락 할 수 있습니다.
Walter Tross

답변:


31

나는 당신이 시도하는 것이 좋습니다 구글 SparseHash (또는 C11 버전 구글 SparseHash-C11를 )하고 필요에 맞는 있는지 확인합니다. 메모리 효율적인 구현과 속도에 최적화 된 구현이 있습니다. 오래 전에 벤치 마크를 수행했는데 속도 측면에서 사용할 수있는 최고의 해시 테이블 구현이었습니다 (단, 단점이 있음).


16
단점이 무엇인지 자세히 설명해 주시겠습니까?
Haywood Jablomey

IIRC, 그것은 메모리 문제였습니다. 요소를 제거 할 때 요소가 파괴되었지만 그 메모리는 여전히 살아 있습니다 (내가 추측하는 캐시로 사용됨).
Scharron

4
@Haywood Jablomey : 가장 큰 단점은 하나 또는 두 개의 값 (요소를 지운 경우)을 분리하고 절대 사용하지 않아야한다는 것입니다. 어떤 경우에는 이것은하기 쉽습니다. 예를 들어, 부정적 int 나 그와 비슷한 경우도 있지만 그렇지 않은 경우도 있습니다.
2010-07-21

3
오늘이 권고를지지 하시겠습니까?
einpoklum

11

이 사용 사례에 맞는 데이터 구조를 가진 C 또는 C ++의 라이브러리는 무엇입니까? 또는 자신의 건물을 어떻게 추천 하시겠습니까? 감사!

LGPL'd Judy 어레이를 확인하십시오 . 나 자신을 사용하지 않았지만 가끔 광고를 받았다.

STL 컨테이너 (std :: hash_map 등)를 벤치마킹 할 수도 있습니다. 플랫폼 / 구현 및 소스 코드 튜닝 (동적 메모리 관리 비용이 많이 드는만큼 사전 할당)에 따라 충분히 성능을 발휘할 수 있습니다.

또한 최종 솔루션의 성능이 솔루션 비용을 능가하는 경우 모든 것을 일반 어레이에 넣을 수있는 충분한 RAM이있는 시스템을 주문할 수 있습니다. 인덱스 별 액세스 성능은 타의 추종을 불허합니다.

추가 / 삭제 작업은 가져 오기 작업보다 훨씬 (100 배) 더 자주 발생합니다.

이는 먼저 알고리즘 개선에 집중하고 싶을 수도 있음을 암시합니다. 데이터를 읽지 않고 쓰기 만한다면 왜 데이터를 쓰나요?


11

기본적으로 boost::unordered_map(또는 tr1기타) 사용하십시오 . 그런 다음 코드를 프로파일 링하고 해당 코드가 병목인지 확인합니다. 그래야만 더 빠른 대체품을 찾기 위해 요구 사항을 정확하게 분석하는 것이 좋습니다.


15
그것은. VS2013 std::unordered_map은 처리의 상대적으로 작은 부분에만 맵을 사용하지만 전체 실행 시간의 90 % 이상을 차지합니다.
Cameron




2

먼저 libmemcache와 같은 기존 솔루션이 필요에 맞는지 확인하십시오.

그렇지 않다면 ...

해시 맵이 귀하의 요구 사항에 대한 확실한 대답 인 것 같습니다. 키를 기반으로 o (1) 조회를 제공합니다. 대부분의 STL 라이브러리는 요즘 일종의 해시를 제공합니다. 따라서 플랫폼에서 제공하는 것을 사용하십시오.

해당 부분이 완료되면 솔루션을 테스트하여 기본 해싱 알고리즘이 요구 사항에 충분한 성능을 제공하는지 확인해야합니다.

그렇지 않은 경우 인터넷에서 찾은 좋은 빠른 해싱 알고리즘을 탐색해야합니다.

  1. 좋은 오래된 소수 곱하기 알고리즘
  2. http://www.azillionmonkeys.com/qed/hash.html
  3. http://burtleburtle.net/bob/
  4. http://code.google.com/p/google-sparsehash/

이것이 충분하지 않은 경우 테스트 한 STL 컨테이너와 위의 해싱 알고리즘 중 하나에서 본 문제를 해결하는 해싱 모듈을 직접 롤링 할 수 있습니다. 결과를 어딘가에 게시하십시오.

오, 그리고 당신이 여러 개의 맵을 가지고 있다는 점이 흥미 롭습니다. 아마도 키가 속한 맵을 구별하고 하나의 거대한 해시에 모든 키 값 쌍을 추가하는 데 사용되는 상위 비트를 사용하여 64 비트 숫자로 키를 사용하여 단순화 할 수 있습니다. 기본 소수 해싱 알고리즘에서 완벽하게 잘 작동하는 10 만 개 정도의 기호가있는 해시를 보았습니다.

수백 개의 맵에 비해 솔루션의 성능을 확인할 수 있습니다. 메모리 프로파일 링 관점에서 더 나을 수 있다고 생각합니다.이 연습을 수행 할 수 있다면 어딘가에 결과를 게시하십시오.

해싱 알고리즘 이상으로 메모리의 지속적인 추가 / 삭제 (피할 수 있습니까?)와 애플리케이션 성능에 더 중요한 CPU 캐시 사용 프로필이 될 수 있다고 생각합니다.

행운을 빕니다


2

기타 컨테이너 템플릿 에서 해시 테이블을 사용해보십시오 . 그것은 closed_hash_map구글의와 같은 속도에 관한 것입니다 dense_hash_map만, 사용 (포함 된 값에 대한 제한 없음)에 쉽게뿐만 아니라 다른 특전이있다.


2

나는 uthash를 제안 할 것이다 . 구조 #include "uthash.h"에 a UT_hash_handle를 추가 한 다음 구조에서 키 역할을 할 하나 이상의 필드를 선택하기 만하면됩니다 . 여기 에 성능에 대한 한마디 .


1

http://incise.org/hash-table-benchmarks.html gcc는 아주 좋은 구현을 가지고 있습니다. 그러나 매우 나쁜 표준 결정을 존중해야합니다.

재해시가 발생하면 모든 반복기가 무효화되지만 개별 요소에 대한 참조와 포인터는 계속 유효합니다. 실제 재해시가 발생하지 않으면 변경되지 않습니다.

http://www.cplusplus.com/reference/unordered_map/unordered_map/rehash/

이것은 기본적으로 표준이 구현이 연결 목록을 기반으로해야한다고 말합니다. 더 나은 성능을 가진 개방 주소 지정을 방지합니다.

Google 스파 스는 개방형 주소 지정을 사용하고 있다고 생각하지만 이러한 벤치 마크에서는 고밀도 버전 만 경쟁 제품을 능가합니다. 그러나 희소 버전은 메모리 사용량면에서 모든 경쟁을 능가합니다. (또한 요소의 수에 대한 고원, 순수한 직선이 없습니다)


1
버킷 인터페이스에도 체인이 필요한 방법을 설명하는 this를 참조하십시오 . 참고 문헌에 대한 요점은 매우 좋습니다. 그것이 유용한 보장이라고 주장하고 말하고 싶은 유혹이 있지만, 많은 경우에 우리는 요소를 다시 찾는 것을 피하기 위해 참조만을 원하며, 일반적인 이유는 조회가 너무 느리기 때문입니다. 참조를 유효하게 유지해야하므로 개방 주소 지정을 사용할 수 있습니다! 그래서 약간 닭고기와 달걀처럼 보입니다. 이것은 2003 년 제안을 인용하고 선택을 명시 적으로 논의합니다.
underscore_d
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.