OpenMP 正确观察计算时间
OpenMP 经验总结
(1) openmp 线程使用范围
(2)openmp 多层嵌套的问题
OpenMP 正确观察计算时间
在使用 openmp的过程中, 使用了简单的 #pragma omp parallel
但是观察计算时间并未得到优化
// 使用 openmp 优化的代码
#include
#include
#include
#include
int main(int argc, char **argv)
{
int m = 1100;
int a[m][m],i, j;
int sum = 0;
const clock_t begin_time
= clock();
omp_set_num_threads(4);
double start =
omp_get_wtime( );
std::cout <<"
NumThreads : "<<
omp_get_max_threads()<<std::endl;
#pragma omp parallel for
private(j) reduction( +:sum) //
将其注释即可观察不使用openmp的情况
for(int k=0; k<100;
k++)
{
for(int i=0; i
for (int j
= 0; j < m; j++)
{
sum = sum
+ 1;
}
}
//std::cout << "Thread ID : " <<
omp_get_thread_num()<<"
sum : " << sum << std::endl;
}
double end =
omp_get_wtime( );
std::cout <<
" sum Total :
" << sum << std::endl;
std::cout << "Time
clock(): "<< float( clock () - begin_time )
/ CLOCKS_PER_SEC <<
std::endl;
std::cout << "Time
wtime(): "<< float( end - start ) <<
std::endl;
return 0;
}
使用 openmp优化的结果
NumThreads : 4
sum
Total : 121000000
Time clock():
0.278465
不使用openmp优化的结果
NumThreads : 4
sum Total : 121000000
Time clock(): 0.21804
可以看出, 不是用的效果甚至更好一些,但是这不符合常识啊。 经过测试原来发现正确的测量方法应该是使用
omp_get_wtime( ), 使用的代码如下。
#include
#include
#include
int main(int argc, char **argv)
{
int m = 1100;
int a[m][m],i, j;
int sum = 0;
const clock_t begin_time
= clock();
omp_set_num_threads(4);
double start =
omp_get_wtime( );
std::cout <<"
NumThreads : "<<
omp_get_max_threads()<<std::endl;
#pragma omp parallel for
private(j) reduction( +:sum)
for(int k=0; k<100;
k++)
{
for(int i=0; i
for (int j
= 0; j < m; j++)
{
sum = sum
+ 1;
}
}
//std::cout << "Thread ID : " <<
omp_get_thread_num()<<"
sum : " << sum << std::endl;
}
double end =
omp_get_wtime( );
std::cout <<
"sum Total : " << sum <<
std::endl;
std::cout << "Time
clock(): "<< float( clock () - begin_time )
/ CLOCKS_PER_SEC <<
std::endl;
std::cout << "Time
wtime(): "<< float( end - start ) <<
std::endl;
return 0;
}
最后的结果如下
NumThreads : 4
sum Total : 121000000
Time clock(): 0.280769
Time wtime(): 0.108388
解释一下, clock() 记录的是cpu的滴答数的,当并行多个进程同时计算, cpu滴答数成倍增加,
所以我们得到的差值并不是真实的时间数, openmp 提供的omp_get_wtime() 才记录的运行时的真实时间,
所以一直错误是没有正确的观察时间。 废了我两个小时解决。
OpenMP 经验总结
(1) openmp 线程使用范围
openmp是基于 “fork-join” 思想搭建的,在构造过程中。
不是很方便构造一个需要伴随着主线程运行的线程(不知道能不能叫做守护线程), 因为在工作中需要开出一个线程用于监听一个 信号, 我使用了
boost::thread 库中生成线程的方法
#include
new_thread_ = new boost::thread(boost::bind(&B::A,
this));
void B::A()
{
while(ros::ok()) // 主要是监测这个
{
sleep(1); // 每隔 1s
检查一次
if(Signal) // updateMap_Signal 是全局更新地图的控制信号,
有两个地方可以发出信号;手都发出与定时更新
{
if(remap())
{
ROS_DEBUG("Updated");
}
Signal = 0;
}
}
return;
}
这样产生的线程, 会伴随着 ros 运行时的状态, 直到主线程死亡。
(2)openmp 多层嵌套的问题
openmp 会根据cpu核心数目,fork处固定数目的线程, 如果产生了嵌套在线程切换过程中也消耗了时间,
此时反而可能拖累了执行的效率。 下面的例子有三个 for 循环, 分别检测一下他们的结果和执行效率。
#include
#include
#include
int main(int argc, char **argv)
{
int m = 1100;
int a[m][m],i, j;
int sum = 0;
const clock_t begin_time
= clock();
omp_set_num_threads(4);
double start =
omp_get_wtime( );
std::cout <<"
NumThreads : "<<
omp_get_max_threads()<<std::endl;
#pragma omp parallel for
private(j) reduction( +:sum)
for(int k=0; k<100;
k++)
{
#pragma omp parallel for
for(int i=0; i
#pragma
omp parallel for
for (int j
= 0; j < m; j++)
{
sum = sum
+ 1;
}
}
//std::cout << "Thread ID : " <<
omp_get_thread_num()<<"
sum : " << sum << std::endl;
}
double end =
omp_get_wtime( );
std::cout <<
"sum Total : " << sum <<
std::endl;
std::cout << "Time
clock(): "<< float( clock () - begin_time )
/ CLOCKS_PER_SEC <<
std::endl;
std::cout << "Time
wtime(): "<< float( end - start ) <<
std::endl;
return 0;
}
嵌套数 解释 时间
2 注释掉第三个 omp 0.189526
1 注释掉第二个和第三个 omp 0.098441
还有很多其它的测试, 但是这里也可以看出,只进行一个 omp 优化反而效率最高。
所以总结的策略是, 将 omp 放置在循环迭代次数最多的地方, 经过测试还发现,多线程的优化大概也就能提升 50%
的效率。
加载中,请稍候......