从库 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++ 中设置环境变量的主要内容,如果未能解决你的问题,请参考以下文章

怎样在Ubuntu中设置环境变量

如何在 Netbeans 中设置环境变量?

如何在生产环境中设置 ASP.NET 5 环境变量

在 git bash 中设置环境变量

如何在fish shell中设置环境变量

如何在 Jupyter notebook 中设置环境变量