내 코드의 일부 지점에서 unordered_map의 모든 요소에 대한 연산을 수행해야합니다. 이것에 대한unordered_map에 대한 OpenMP/__ gnu_parallel
std::unordered_map<size_t, double> hastTable;
#pragma omp for
for(auto it = hastTable.begin();
it != hastTable.end();
it ++){
//do something
}
이유는, unordered_map도의 반복자는 더 랜덤 액세스 반복자 없다는 것을 :이 과정 내가 OpenMP를 사용하려는하지만 순진 접근 방식은 작동하지 않습니다을 가속화하기 위해. 대신에 for_each에서 작동하는 __gnu_parallel 지시문을 사용해 보았습니다. 그러나 다음 코드는
#include <parallel/algorithm>
#include <omp.h>
__gnu_parallel::for_each (hashTable.begin(), hashTable.end(),[](std::pair<const size_t, double> & item)
{
//do something with item.secon
});
(GCC 4.8.2)
g++ -fopenmp -march=native -std=c++11
병렬로 실행되지 않습니다 컴파일. unordered_map을 벡터로 바꾸고 동일한 __gnu_parallel 지시문을 사용하면 병렬로 실행됩니다.
정렬되지 않은지도의 경우 왜 병렬로 실행되지 않습니까? 해결 방법이 있습니까?
다음은 간단한 코드를 제공하며 문제가 재현됩니다.
#include <unordered_map>
#include <parallel/algorithm>
#include <omp.h>
int main(){
//unordered_map
std::unordered_map<size_t, double> hashTable;
double val = 1.;
for(size_t i = 0; i<100000000; i++){
hashTable.emplace(i, val);
val += 1.;
}
__gnu_parallel::for_each (hashTable.begin(), hashTable.end(),[](std::pair<const size_t, double> & item)
{
item.second *= 2.;
});
//vector
std::vector<double> simpleVector;
val = 1.;
for(size_t i = 0; i<100000000; i++){
simpleVector.push_back(val);
val += 1.;
}
__gnu_parallel::for_each (simpleVector.begin(), simpleVector.end(),[](double & item)
{
item *= 2.;
});
}
나는 당신의 답변을 기다리고 있습니다.
고맙습니다. 빈 버킷의 주요 문제점은 빈 버킷을 많이 다루는 스레드가 다른 스레드보다 훨씬 빠르며 유휴 상태로 머문다는 것입니다. 아니면 다른 우려 사항이 있습니까? 당신의 생각은 효과가 있지만 여전히 unordered_maps에 대한 위의 접근 방식이 작동하지 않는 이유는 여전히 흥미 롭습니다. – Christian
"... 많은 양의 빈 버킷이 훨씬 빠릅니다 ..."- 오른쪽, 빈 버킷 클러스터 또는 과도하게 충돌 한 버킷이지만 합리적인 해시를 사용하면 모두 평균을 산출해야합니다. "왜"에 관해서는 - 당신의 질문에서 말했듯이,'unordered_map' 반복자는 무작위 접근이 아닙니다 ... 그것은 평행화 루틴이 아마 반복 오버 헤드가 데이터 요소마다 비교할 때 중요하다고 가정하기 때문에 신뢰할 수있는 설명입니다 처리 과정에서 알 수없는 양의 바이어스는 같은 시간에 완료되도록 반복이 진행됨에 따라 작은 배치를 연속적으로 생성하려고합니다. –
물론 요소 별 처리 시간이 지배적 인 경우 요소에 대한 첫 번째 복사 포인터를 벡터로 반복 한 다음 벡터에서 병렬 처리 할 수 있습니다. –