2

So basically I am trying to set an environment variable in my C++ code to force the number of threads to be 1. I am using multiple machine learning libraries which by default use OpenMP and can be forced to operate in single thread mode by setting the following environment variable: OMP_NUM_THREADS=1

Here's my issue. I want to set this environment variable from within a library I am building.

When I set the environment variable from my main function (executable linking against the library I am building) then it works as expected (only 1 thread is used during the execution of the program):

    auto implPtr = FRVT_11::Interface::getImplementation();
    implPtr->initialize(CONFIG_DIR);
    char ompEnv[]="OMP_NUM_THREADS=1";
    putenv( ompEnv );
    // More code

However, if I try to set the environment variable from within the library I am building (for example from within the getImplementation function), then the number of threads used is 4 instead of 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>();
}

Any ideas why this would be the case? I am building and shipping the library so I need the number of threads to be set from within the library.

7
  • I think the keyword here is "environment". The environment you affect by setting variables when you program runs is ... what? Commented Aug 5, 2019 at 2:51
  • Sorry I don't think I quite understand. Should they not be both referring to the same environment? I'm sorry, I'm somewhat of a beginner. Commented Aug 5, 2019 at 2:54
  • Your program can't do much to affect its own environment, but have full control over subprocesses etc. Commented Aug 5, 2019 at 2:55
  • Possible duplicate of How can I set the number of OpenMP threads from within the program? Commented Aug 5, 2019 at 7:40
  • 1
    Please take a careful look at the duplicate. Even if you succeed in changing your environment variable consistently - it is still not a correct way to change the number of OpenMP threads at runtime. Commented Aug 5, 2019 at 7:41

1 Answer 1

2

Your "library function" version is undefined behavior.

Your "main function" version is also likely undefined behavior, as an extra bonus, but you aren't aware of it, yet.

From the Linux version of the putenv(3) manual page (other OS implementations are likely the same):

The string pointed to by [the parameter to putenv()] becomes part of the environment, so altering the string changes the environment.

That's your big, honking, alarm bell: you better not even think of touching this string, ever again, even with a 10-foot pole, because it is now a part of the environment.

In your shared library version:

char ompEnv[]="OMP_NUM_THREADS=1";

This array is a local variable in the function. Therefore, this array gets destroyed when this function returns. But this array is also passed as a parameter to putenv(). Grand total: as soon as this function returns, one of your environment variables is now a dangling pointer.

There is no sufficient information to conclusively prove that your "main function" version is also undefined behavior, but it's highly likely, too.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the detailed explanation. Moving char ompEnv to a member variable of the class and using that solved the problem!
This fixes the issue with ensuring that the envirable is correctly set, but there is no specification of when the OpenMP implementation reads the environment, so this is still not guaranteed to achieve he desired effect. (It could read it in a static initializer before main is called, for instance, or consider what happens if one of the other libraries is called before your code is even dlopened and loaded into the process). Changing the envirable after it has been read will have no effect on the number of OpenMP threads used.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.