我刚刚开始使用OpenMP指令来使用多个线程。然而,这段代码使用单线程版本运行得最快。在我看来,算法应该很好地扩展,因为计算是独立的。这里发生了什么事?我该如何改进代码?
#include <omp.h>
std::vector<Track> interpolateTracks(const std::vector<Track>& tracks, double segmentLength) {
typedef std::vector<Track>::const_iterator iterator;
std::vector<Track> list;
#pragma omp parallel shared(list, tracks, segmentLength)
{
std::vector<Track> local;
iterator myBegin = threadBegin(tracks.begin(), tracks.end());
iterator myEnd = threadEnd(tracks.begin(), tracks.end());
for (iterator i = myBegin; i < myEnd; ++i) {
const Track& t = *i;
TrackInterpolator interpol(t);
const Track& result = interpol.bySegmentLength(segmentLength);
local.push_back(result);
}
#pragma omp critical
{
list.insert(list.end(), local.begin(), local.end());
std::cout << "Done: " << omp_get_thread_num() << std::endl;
}
}
return list;
}
函数beginThread(begin, end)
和endThread(begin,end)
根据当前线程数和线程数返回begin
和end
定义的范围的小块。
以下是他们的实施:
#include <omp.h>
template <class I>
I threadBegin(I begin, I end) {
int part = omp_get_thread_num();
int parts = omp_get_num_threads();
double chunk = (end - begin)*1.0/parts;
ptrdiff_t diff = (ptrdiff_t) (chunk*part);
return begin + diff;
}
template <class I>
I threadEnd(I begin, I end) {
//the end of i is the begin of i+1
int part = omp_get_thread_num() + 1;
int parts = omp_get_num_threads();
if (part == parts) {
return end;
} else {
double chunk = (end - begin)*1.0/parts;
ptrdiff_t diff = (ptrdiff_t) (chunk*part);
return begin + diff;
}
}
我在具有16个内核的linux机器上运行代码。
不幸的是我只能访问有点过时的gcc((SUSE Linux)4.5.1 20101208),以防这可能是原因。
P.S。我的第一个版本在 critical 部分中使用了list.push_back(..)
的并行for循环,这比在此处发布的变体更慢。
答案 0 :(得分:1)
嗯,你的代码似乎是正确的,但是我看到了可能存在的性能问题:
以下是我的建议: