从库 C++ 中设置环境变量
Posted
技术标签:
【中文标题】从库 C++ 中设置环境变量【英文标题】:Setting environment variable from within library C++ 【发布时间】:2019-08-05 02:47:30 【问题描述】:所以基本上我试图在我的 C++ 代码中设置一个环境变量来强制线程数为 1。我正在使用多个机器学习库,默认情况下使用 OpenMP
并且可以强制在单线程中运行通过设置以下环境变量模式:OMP_NUM_THREADS=1
这是我的问题。我想在我正在构建的库中设置这个环境变量。
当我从我的主函数设置环境变量(针对我正在构建的库的可执行链接)时,它会按预期工作(在程序执行期间仅使用 1 个线程):
auto implPtr = FRVT_11::Interface::getImplementation();
implPtr->initialize(CONFIG_DIR);
char ompEnv[]="OMP_NUM_THREADS=1";
putenv( ompEnv );
// More code
但是,如果我尝试从我正在构建的库中设置环境变量(例如从 getImplementation
函数中),那么使用的线程数是 4 而不是 1:
// This does not work
std::shared_ptr<FRVT_11::Interface> FRVT_11::Interface::getImplementation()
char ompEnv[]="OMP_NUM_THREADS=1";
putenv( ompEnv );
return std::make_shared<MyImplementation>();
任何想法为什么会这样?我正在构建和运送库,所以我需要从库中设置线程数。
【问题讨论】:
我觉得这里的关键词是“环境”。程序运行时通过设置变量影响的环境是……什么? 对不起,我觉得我不太明白。他们不应该都指的是同一个环境吗?对不起,我有点初学者。 你的程序对自身环境影响不大,但可以完全控制子进程等 How can I set the number of OpenMP threads from within the program?的可能重复 请仔细查看副本。即使您成功地一致更改了环境变量 - 在运行时更改 OpenMP 线程数仍然不是正确的方法。 【参考方案1】:您的“库函数”版本是未定义的行为。
作为额外奖励,您的“主要功能”版本也可能是未定义的行为,但您还没有意识到这一点。
来自putenv(3)
手册页的 Linux 版本(其他操作系统实现可能相同):
[putenv() 的参数] 指向的字符串成为 环境,所以改变字符串会改变环境。
那是你的大喇叭警钟:你最好不要再想触碰这根弦,即使是用一根 10 英尺长的杆子,因为它现在是环境的一部分。
在您的共享库版本中:
char ompEnv[]="OMP_NUM_THREADS=1";
这个数组是函数中的一个局部变量。因此,这个数组在这个函数返回时被销毁。但是这个数组也作为参数传递给putenv()
。总计:一旦此函数返回,您的环境变量之一现在就是一个悬空指针。
没有足够的信息最终证明您的“主要功能”版本也是未定义的行为,但也很有可能。
【讨论】:
感谢您的详细解释。将char ompEnv
移动到类的成员变量并使用它解决了问题!
这解决了确保envirable设置正确的问题,但是没有说明OpenMP实现何时读取环境,因此仍然不能保证达到他想要的效果。 (例如,它可以在调用 main 之前在静态初始化程序中读取它,或者考虑如果在您的代码甚至 dloped 并加载到进程中之前调用其他库之一会发生什么)。读取后更改 enrable 不会影响使用的 OpenMP 线程数。以上是关于从库 C++ 中设置环境变量的主要内容,如果未能解决你的问题,请参考以下文章