了解有关fork的OpenMP缺点 [英] Understanding OpenMP shortcomings regarding fork

查看:189
本文介绍了了解有关fork的OpenMP缺点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解它们在这里是什么意思.为什么该程序会挂起"?

I wish to understand what do they mean here. Why would this program "hang"?

来自 https://bisqwit.iki.fi/story/howto/openmp/

OpenMP和fork()值得一提的是,在 调用fork()的程序需要特殊考虑.这 问题只影响海湾合作委员会; ICC不受影响.如果您的程序 打算使用daemonize()或其他方法成为后台进程 类似的方法,您不能在派生之前使用OpenMP功能. 使用OpenMP功能后,只有在以下情况下才允许使用fork: 子进程不使用OpenMP功能,或者作为一个 全新的过程(例如在exec()之后).

OpenMP and fork() It is worth mentioning that using OpenMP in a program that calls fork() requires special consideration. This problem only affects GCC; ICC is not affected. If your program intends to become a background process using daemonize() or other similar means, you must not use the OpenMP features before the fork. After OpenMP features are utilized, a fork is only allowed if the child process does not use OpenMP features, or it does so as a completely new process (such as after exec()).

这是一个错误程序的示例:

This is an example of an erroneous program:

#include <stdio.h>   
#include <sys/wait.h>   
#include <unistd.h>

void a(){
    #pragma omp parallel num_threads(2)
    {
        puts("para_a"); // output twice
    }
    puts("a ended"); // output once   
}

void b(){
    #pragma omp parallel num_threads(2)
    {
        puts("para_b");
    }
    puts("b ended");   
}

int main(){    
    a();   // Invokes OpenMP features (parent process)   
    int p = fork();    
    if(!p){
        b(); // ERROR: Uses OpenMP again, but in child process
        _exit(0);    
    }    
    wait(NULL);    
    return 0;   
}

运行时,该程序挂起,从未到达输出"b"的行 已结束".目前没有解决方法,因为libgomp API没有 指定可用于准备调用fork()的函数.

When run, this program hangs, never reaching the line that outputs "b ended". There is currently no workaround as the libgomp API does not specify functions that can be used to prepare for a call to fork().

推荐答案

要扩展Andrew Henle的答案,fork(2)要做的是创建第二个进程,该进程通过写时复制共享调用线程的整个内存空间(CoW)内存映射.子进程处于尴尬的境地-它是具有相同状态的父线程的副本(系统调用的返回值以及计时器和资源使用计数器之类的其他东西除外),并且可以访问其所有内存和打开的文件描述符,但除了进行fork(2)调用的线程外,没有任何其他执行线程.尽管可以采取一些预防措施,但可以将其用作多线程的粗略形式(并且在Unix引入真正的LWP之前已将其用于此目的),但99%的情况fork(2)都具有单个目的-生成子进程,而child在派生之后立即调用execve(2)(或其在标准C库中的前端之一).考虑到这一事实,有一个甚至更极端的版本称为vfork(2),它甚至不创建父级内存的CoW映射,而是直接使用其页表,从而有效地在独立进程和线程之间创建了一个混合体.在这种情况下,甚至不允许子级进行异步信号安全的函数调用,因为它在父级的堆栈上进行操作.

To expand on Andrew Henle's answer, what fork(2) does is create a second process that shares the entire memory space of the calling thread via copy-on-write (CoW) memory mappings. The child process is in an awkward situation - it is a replica of the parent thread with the same state (except the return value of the system call and some other things like timers and resource use counters) and access to all its memory and open file descriptors but without any other thread of execution besides the one that made the fork(2) call. While with some precautions this can be used as a crude form of multithreading (and it was used for that purpose before true LWPs were introduced in Unix), 99% of the cases fork(2) serves a singular purpose - to spawn child processes whereas the child calls execve(2) (or one of its front-ends in the standard C library) immediately after the fork. In recognition of that fact, there is an even more extreme version called vfork(2) that doesn't even create CoW mappings of the parent's memory but directly uses its page tables, effectively creating a hybrid between a standalone process and a thread. The child in that case is not even allowed to make async-signal-safe function calls because it operates on the parent's stack.

请注意,OpenMP规范并未涵盖与其他线程和/或过程控制机制的任何交互,因此,即使它可以与某些OpenMP实现一起使用,您的示例也不是正确的OpenMP程序.

Note that the OpenMP specification does not cover any interaction with other threading and/or process control mechanisms, thus, even if it might work with some OpenMP implementations, your example is not a correct OpenMP program.

这篇关于了解有关fork的OpenMP缺点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆