如何改进此代码以便在多线程环境下运行
How to improve this code in order to be run multithreaded?
我刚刚开始使用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),以防这可能是原因。
第页。S.我的第一个版本在关键部分使用了list.push_back(..)
的并行for循环,这甚至比这里发布的变体还要慢。
好吧,您的代码似乎是正确的,但我看到的可能是性能问题:
- 当然,关键部分是性能杀手,尤其是在计算不太昂贵和/或轨迹矢量不是很大的情况下
- 存储"轨迹"对象的事实意味着,当将它们从局部向量移动到最终向量时,必须复制构造它们
- 你知道向量的最终大小,但你可以动态地增长它们
- threadBegin和threadEnd函数使用浮点运算和FP到整数的转换。这些,尤其是转换,比执行等效的整数运算要慢得多
以下是我的建议:
- 在矢量中存储std::unique_ptr
- 将矢量预先分配到最终大小
- 为了避免最后需要一个关键部分,我有两种选择:a) 直接在最终数组中工作,但要找到正确的块。由于它是预先分配的,所以您不必保护它。b) 在局部向量中工作,然后从线程内复制到预分配的最终向量的正确块
- 使用整数数学计算你的区块——你应该能够在分叉之前完成大部分计算,然后只需更正最后一个区块的大小
相关文章:
- 如何正确取消析构函数中的 Boost deadline_timer(在多线程环境中)?
- 为什么添加延迟会提高此多线程环境中的数据吞吐量?
- Qt::D irectConnection在多线程环境中使用时如何工作?
- 在多线程环境中正确销毁对象
- 多线程环境中C++内存访问
- 为多线程环境包装 c++ new/delete 的安全/好方法
- 在多线程环境中使用 std::call_once() 初始化
- 在多线程环境中交换C 地图对象
- 在多线程环境中使用 libcurl 会导致与 DNS 查找相关的性能非常慢
- 暂停和恢复多线程环境中另一个线程的线程C++技术建议
- 在多线程环境中,什么可能导致"bad file descriptor"?
- 多线程环境中的输出字符串流出现问题
- 信号处理程序在多线程环境中的功能
- 在多线程环境中使用Mysql++的问题
- C++-SQLite3在多线程环境中泄漏句柄
- 如何改进此代码以便在多线程环境下运行
- 在多线程环境中使用atomic保护两个变量
- 多线程环境中的文档锁定
- XSetWMProtocols 和 glXCreateContext 在多线程环境中调用顺序
- 多线程环境 (OpenMP) 中的 OpenCV 会导致分段错误