2012-11-07 40 views
1

我刚刚发现gcc的OpenMP实现(libgomp)不调用pthread_exit()。 我需要使用perfsuite(用于剖析)。让GCC在转换OpenMP并行代码时调用pthread_exit

有没有什么办法可以告诉GCC在将OpenMP代码转换为pthread代码的同时,在OpenMP的并行部分的末尾包含pthread_exit()?

我使用的是GCC 4.7.0和Perfsuite 1.1.1。

回答

3

libgomp实现线程池。创建完成后,池中的线程将保持空闲状态,直到它成为线程组的成员。团队完成工作后,线程会进入空闲循环,直到再次发出信号。游泳池按需增长,但从不缩水。线程仅在程序结束时发出信号退出。

您可以阅读在4.7.x分支here中实现线程池和团队的libgomp代码。

池线程以这种方式终止:libgomp通过名称team_destructor()注册析构函数。只要main()函数返回,exit(3)被调用或libgomp库通过调用dlclose(3)(如果先前加载了dlopen(3))而被卸载,就会调用它。析构函数删除一个pthreads键的名称为gomp_thread_destructor,该名称具有由删除触发的相关析构函数gomp_free_thread()gomp_free_thread()使池中的所有线程执行gomp_free_pool_helper()作为他们的下一个任务。 gomp_free_pool_helper()调用pthread_exit(3),因此池中的所有线程都不存在。

这里是一个不错的ASCII画面相同的过程:

main() returns, exit() called or library unloaded 
    | 
    | 
team_destructor() deletes gomp_thread_destructor 
    | 
    | 
gomp_free_thread() called by pthreads on gomp_thread_destructor deletion 
    | 
    +-------------------------+---------------------------+ 
    |       |       | 
gomp_free_pool_helper() gomp_free_pool_helper() ... gomp_free_pool_helper() 
installed as next task installed as next task  installed as next task 
    |       |       | 
    |       |       | 
pthread_exit(NULL)  pthread_exit(NULL)  ... pthread_exit(NULL) 

注意,这只是在程序执行结束时发生一次,而不是在每个区域parallel的结束。

+0

嗨Hristo,谢谢你的回答。据我了解,当程序退出,即线程获取信号时,它不会调用pthread_exit()。似乎我需要更改此文件(team.c)的代码来执行此操作。是对的吗?如果是这样,有没有简单的方法来做到这一点? – Rakib

+1

线程在'gomp_thread_start()'的后半部分运行循环,只要它们具有在对接屏障后执行的函数,否则它们将退出循环并简单地返回。当线程调用'pthread_exit'时有一种情况,'libgomp'在运行时用'dlopen(3)'加载时就是这种情况。有一个关键的'gomp_thread_destructor'与一个关联的析构函数'gomp_free_thread()'和一个名为'team_destructor()'的文件析构函数被注册。当你把库关闭时,文件析构函数被调用,并且它使得所有的团队线程都调用pthread_exit。 –

+1

对不起,我的错误 - 函数'__attribute __((析构函数))'也在'main()'返回后调用。这意味着池线程肯定会到达他们称之为“pthread_exit”的地方,但不会在'main'函数返回之前。不幸的是,'libgomp' API对用户不可用,并且您不能在'main()'结束之前调用池析构函数。 –

相关问题