Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7944 Discussions

icc 18 renaming symbols internally - omp_set_num_threads

Nicholas_Devenish
2,213 Views

I've found icc18 renaming symbols internally. Basic test.cpp:

extern "C"
{
  void omp_set_num_threads(int num_threads);
}

void somefun(void)
{
  omp_set_num_threads(3);
}

Attempt to compile with:

$ icpc test.cpp
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/tmp/icpcY3L2xB.o: In function `somefun()':
test.cpp:(.text+0x6): undefined reference to `ompc_set_num_threads'

Essentially: The omp_set_num_threads has been renamed to ompc_set_num_threads, as though it were a magic name being handled specially internally to the compiler?. Even if this was required, I've not enabled openmp. This specific sample just shows the renaming - I'm not expecting it to otherwise compile - we've got code in our project that stubs out openmp if OpenMP is not turned on, and this transformation breaks the code (because it links to a stub where omp_set_num_threads definitely exists, but is no longer looking for that symbol).

icc 17 doesn't have this issue. Why is it here, and how do I turn it off?

0 Kudos
14 Replies
Viet_H_Intel
Moderator
2,213 Views

 

I see omp_set_num_threads has been renamed, but it's defined in libiomp5; you would need to link with -qopenmp to resolve it.

$ nm libiomp5*|grep ompc_set_num_threads
0000000000001dd0 T ompc_set_num_threads
                 U ompc_set_num_threads
000000000006bcb0 T ompc_set_num_threads
000000000006bcb0 T ompc_set_num_threads
 
Can you provide a complete test case showing it works with 17.0 but breaks with 18.0?
 
Thanks,
Viet 
0 Kudos
Nicholas_Devenish
2,213 Views

In this specific case, I didn't want to -qopenmp. I want my own symbol called omp_set_num_threads, and to link to this in cases where we don't want to enable openmp (the project I'm working on has written an empty abstraction so that they can write openmp control code with or without openmp turned on, without having to #ifdef, and to python wrap. I'm not saying that this is a good approach, but unfortunately it's the one we've got).

Attached is a complete example with makefile that compiles and runs on icc17 but gives the same error as above on icc18. A file with the contents stub.cpp:

extern "C" void omp_set_num_threads(int) { }

Should define the symbol, and and correctly does, whether compiled as static:

$ icpc -c stub.cpp -o stub.o
$ nm stub.o
                 U __gxx_personality_v0
0000000000000000 T omp_set_num_threads

Or shared:

$ icpc -shared -fPIC stub.cpp -o libstub.so
$ nm libstub.so | grep threads
0000000000000750 T omp_set_num_threads

I should then be able to link to this symbol (indeed, this is the most basic example of sharing codes between translation units) by just declaring it and specifying the library to link (shared) or object file to include (static) e.g.

// Explicitly declare, *not define* the function so we can call it
extern "C" void omp_set_num_threads(int);

int main(int, char**)
{
  omp_set_num_threads(4);
}

And then compile (static version, to avoid -L path complexity) with

$ icpc -o main main.cpp stub.o

But this fails on icc18 with the above ompc_set_num_threads error, even though that's not a symbol I've used anywhere in my program. As a simple test cross-section, icc17, gcc4.8.5 and clang5.0 works fine. icc18 seems to treat openmp symbols as special and rename them, even if openmp hasn't been turned on with -qopenmp. Since to my knowledge no compiler allows you to swap out the openmp implementations at runtime this is perhaps justifiable, but surely not when openmp isn't requested?

As far as I'm aware omp_set_num_threads isn't a protected symbol and theoretically I should be allowed to define it myself? My question is whether this can be turned off, and, I guess, are there any otherwise valid symbols that I'm not allowed to use with icc?

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,213 Views

Viet,

I agree with Nicholas that the compiler should not rename the user supplied symbols. Consider additional factors to Nicholas's desire to use his own stubs.

a) Use of previous compiled static lib or .dll having format without renaming.
b) Use of older Intel libiomp5 (due to bug in newer libiomp5 or difference in implementation).
c) For reasons known to user, compile code to be linked with GCC OpenMP runtime library.

Jim Dempsey

0 Kudos
jase439
Beginner
2,028 Views

Does anyone know the status of this issue? My client falls into Option C that Jim cites in that they have a shared module built with ICC18 but the calling app is linked against the GCC OpenMP runtime. This results in the undefined symbol error mentioned by the OP.

 

Under-the-hood renaming of user-supplied public symbols should be eschewed. This issue is still present in the latest legacy compiler supplied in the HPC toolkit.

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,016 Views

>> they have a shared module built with ICC18 but the calling app is linked against the GCC OpenMP runtime...

It sounds like their shared module (built with ICC18) is itself using OpenMP as opposed to or in addition to being called from GCC OpenMP.

I do not think it is valid/appropriate to blend OpenMP implementations.

 

I'd suggest, if possible, you supply GCC built shell functions containing the #pragma omp ... that call your ICC build acceleration routines..

Jim Dempsey

0 Kudos
jase439
Beginner
2,007 Views

I ended up moving the OMP routines in the host application into a separate shared library which allowed me to eliminate the OpenMP dependency from the host application altogether. The "mixing" is an unfortunate side-effect of the host application needing to be compiled with GCC for some of their instrumentation and coverage tools whereas the ICC18 compiled module is "opaque" to the app and cannot be recompiled (don't even think it can be built with GCC in its present form).

This hasn't presented an issue in the past because the client historically used an older ICC compiler which did not introduce this strange symbol-renaming behavior - but now in the process of moving to the oneAPI license and compiler tools. In any case, I am curious if Intel has any intention of evaluating the OP's bug report or if it just died on the vine and this is just the way it is moving forward.

0 Kudos
Viet_H_Intel
Moderator
1,986 Views

Seems like we are not going to fix this issue. At -O2, the compiler Front End changes some known lib functions into intrinsics to enable more optimizations. There are workarounds such as using -O1, or the function can be renamed.

0 Kudos
Viet_H_Intel
Moderator
2,213 Views

 

Hi Nicholas,

Thankd for your test case. It's clear to me now. I just reported this issue to our developer and will keep you posted.

Viet

0 Kudos
Viet_H_Intel
Moderator
2,213 Views

Internal bug number is: CMPLRIL0-30689

0 Kudos
Andrey_C_Intel1
Employee
2,213 Views

I agree the Intel compiler behaves not user friendly in this particular case.  Though the intention to implement own OpenMP runtime and use it with Intel compiler which has its own runtime looks unclear in general.  This use case does not look reliable in general.  Would it be better to just use stubs library provided by the compiler?  This is simple, just specify -qopenmp-stubs compiler option.  BTW, declaring OpenMP interfaces manually is also not a conforming way to use OpenMP runtime APIs, as the specification requires to include standard header omp.h for this.

-- Andrey

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,971 Views

>>But this fails on icc18 with the above ompc_set_num_threads error, even though that's not a symbol I've used anywhere in my program. 

Although you have a work around, here is something else you could keep in mind.

 

From your description, ICC is generating ompc_set_num_threads when it sees omp_set_num_threads (iow it uses an alias). The "hack" I suggest is to add ompc_set_num_threads to your gcc build that simply calls (gcc's) omp_set_num_threads (with int arg).

 

Jim Dempsey

0 Kudos
jase439
Beginner
1,953 Views

Thanks Jim. This was actually the first solution I employed to resolve this problem (providing a global definition for void ompc_set_num_threads(int) to the GCC-compiled host application). Seemed reasonable, however, the error persisted. I'm not sure if the compiler intrinsic has a different signature under the hood than omp_set_num_threads. I didn't really waste much effort trying to divine why this didn't work and simply moved forward with the solution given earlier.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,944 Views

Did you add extern "C" to the function?

Jim Dempsey

0 Kudos
jase439
Beginner
1,927 Views

Yes, I did. It may have been some other silly detail I missed, but it wasn't immediately apparent to me. I didn't really invest much time in this solution beyond this since I had a working solution that improved the overall design of the software by decoupling core algorithms from the host application (albeit with a bit more work).

0 Kudos
Reply