我刚刚发现gcc的OpenMP实现(libgomp)不调用pthread_exit()。 我需要使用perfsuite(用于剖析)。让GCC在转换OpenMP并行代码时调用pthread_exit
有没有什么办法可以告诉GCC在将OpenMP代码转换为pthread代码的同时,在OpenMP的并行部分的末尾包含pthread_exit()?
我使用的是GCC 4.7.0和Perfsuite 1.1.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。
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
的结束。
嗨Hristo,谢谢你的回答。据我了解,当程序退出,即线程获取信号时,它不会调用pthread_exit()。似乎我需要更改此文件(team.c)的代码来执行此操作。是对的吗?如果是这样,有没有简单的方法来做到这一点? – Rakib
线程在'gomp_thread_start()'的后半部分运行循环,只要它们具有在对接屏障后执行的函数,否则它们将退出循环并简单地返回。当线程调用'pthread_exit'时有一种情况,'libgomp'在运行时用'dlopen(3)'加载时就是这种情况。有一个关键的'gomp_thread_destructor'与一个关联的析构函数'gomp_free_thread()'和一个名为'team_destructor()'的文件析构函数被注册。当你把库关闭时,文件析构函数被调用,并且它使得所有的团队线程都调用pthread_exit。 –
对不起,我的错误 - 函数'__attribute __((析构函数))'也在'main()'返回后调用。这意味着池线程肯定会到达他们称之为“pthread_exit”的地方,但不会在'main'函数返回之前。不幸的是,'libgomp' API对用户不可用,并且您不能在'main()'结束之前调用池析构函数。 –