我想从Python调用一些OpenMP程序,改变线程数(OMP_NUM_THREADS
)及其绑定(OMP_PLACES
,OMP_PROC_BIND
)。我写了这个程序:
import os
from ctypes import cdll
lib = cdll.LoadLibrary("/home/fayard/Desktop/libf.so")
nb_socket = 2
nb_core_per_socket = 14
nb_thread_per_core = 2
n = nb_socket * nb_core_per_socket * nb_thread_per_core
for nb_thread in range(1, n + 1):
os.environ['OMP_NUM_THREADS'] = str(nb_thread)
print("nb_thread: {}, omp_get_num_threads: {}".format(
nb_thread, lib.num_threads()))
OpenMP库如下:
#include <omp.h>
extern "C" {
int num_threads() {
int ans;
#pragma omp parallel
{
#pragma omp single
ans = omp_get_num_threads();
}
return ans;
}
}
并编译为:
g++ -c -fPIC -fopenmp f.cpp -o f.o
g++ -shared -fopenmp -Wl,soname,libf.so -o libf.so f.o
当我运行python program.py
时,我得到:
nb_thread: 1, omp_get_num_threads: 56
...
nb_thread: 56, omp_get_num_threads: 56
这不是我想要的!我也意识到,当使用具有完全相同参数的英特尔编译器编译时,我得到:
nb_thread: 1, omp_get_num_threads: 1
...
nb_thread: 56, omp_get_num_threads: 1
对于出了什么问题的任何想法?
答案 0 :(得分:1)
环境变量仅控制内部控制变量的初始设置。
[OpenMP 4.5] 4。环境变量
OpenMP实现忽略了程序启动后对环境变量的修改,即使由程序本身修改也是如此。但是,通过使用适当的指令子句或OpenMP API例程,可以在执行OpenMP程序期间修改某些ICV的设置。
您可以在omp_set_num_threads
周围编写一个小包装,但不能动态更改绑定。
不幸的是,unload shared librareies in ctypes没有干净的解决方案。另一种方法是使用subprocess
运行实际程序,而不是加载库,但是你有一个不同的接口。
如果必须使用共享库并控制动态绑定,则可以在python调用的共享库中手动对sched_setaffinity
进行一些魔术。
gcc和intel运行时行为不同的原因可能是因为你在加载库后设置了环境变量,并且它们的初始化方式不同。