我剛開始使用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)
和根據當前線程數目和線程的數目由begin
和end
定義的範圍endThread(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;
}
}
我運行在Linux機器上的代碼有16個內核。
不幸的是,我只能訪問過時的gcc((SUSE Linux)4.5.1 20101208),以防萬一這可能是原因。
P.S.我的第一個版本使用並行for循環與list.push_back(..)
在關鍵部分,這比在此處發佈的變體更慢。
嗯,這是創建OpenMP的一種創造性方式,但最大的問題是 - 'threadBegin'和'threadEnd'函數是什麼樣子的? –
哪一段代碼是最耗時的? 'interpol.bySegmentLength(segmentLength)'裏面發生了什麼;'? – Tudor
我剛剛添加了實現。 'interpol.bySegmentLength(segmentLength);'和'TrackInterpolator interpol(t);'應該是最耗時的調用。 – Sebastian