我正在尝试包装一个最小的 C 库,其中包含一个文件“locks.h”,其中包含
#ifndef LOCKS_H
#define LOCKS_H
void f(void);
#endif
和“locks.c”包含
#include <stdio.h>
void f(void) {
#pragma omp parallel
{
fprintf(stderr, "Hello World!\n");
}
return;
}
使用 swig,使用包含 swig 输入文件“locks.i”
%module locks
%{
#define SWIG_FILE_WITH_INIT
#include "locks.h"
%}
void f(void);
然后我使用
创建并构建包装器swig -python locks.i
gcc -fPIC -shared -I/usr/include/python3.6/ -fopenmp locks.c locks_wrap.c -g -o _locks.so
以及快速测试
python3 -c "import locks; locks.f()"
似乎按预期工作。
但是,当我调用函数 f
两次时,一次从 python 主进程调用,一次从子进程调用,如下所示:
from multiprocessing import Process
import locks
locks.f()
print('Launching Process')
p = Process(target=locks.f)
p.start()
p.join()
print(p.exitcode)
代码在子进程的调用中挂起,仅打印
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Launching Process
Hello World!
在 Python 3.6 和
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Launching Process
在具有 4 核和 8 个超线程的 Intel CPU 上的 Python 3.8 中。
如果我只从子进程中调用该函数,而不是在两个进程中调用该函数,则子进程中的调用也会按预期成功。
目标系统是 64 位 Linux(本例中为 Ubuntu 18.04)。
我该如何解决这个问题?
最佳答案
正如 Zulan 所指出的在评论中,核心问题似乎是 one cannot call OpenMP functions after a fork
.
幸运的是,Python 多处理允许您使用 set_start_method()
函数来请求它不是 fork ,而是从头开始生成全新的解释器进程。
因此通过将 python 脚本调整为
import multiprocessing as mp
import locks
if __name__ == '__main__':
mp.set_start_method('spawn')
locks.f()
print('Launching Process')
p = mp.Process(target=locks.f)
p.start()
p.join()
print(p.exitcode)
问题已解决。
关于python - 为什么当通过 swig 从子进程调用时,使用 OpenMP 的共享库中的函数会挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59251966/