从Python和环境变量

时间:2017-01-12 15:09:26

标签: python c openmp ctypes

我想从Python调用一些OpenMP程序,改变线程数(OMP_NUM_THREADS)及其绑定(OMP_PLACESOMP_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

对于出了什么问题的任何想法?

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运行时行为不同的原因可能是因为你在加载库后设置了环境变量,并且它们的初始化方式不同。