Community
cancel
Showing results for 
Search instead for 
Did you mean: 
420 Views

icc 18 renaming symbols internally - omp_set_num_threads

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
420 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 
420 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?

jimdempseyatthecove
Black Belt
420 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

Jason_B_
Beginner
235 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.

jimdempseyatthecove
Black Belt
223 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

Jason_B_
Beginner
214 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.

Viet_H_Intel
Moderator
193 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.

Viet_H_Intel
Moderator
420 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

Viet_H_Intel
Moderator
420 Views

Internal bug number is: CMPLRIL0-30689

Andrey_C_Intel1
Employee
420 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

jimdempseyatthecove
Black Belt
178 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

Jason_B_
Beginner
160 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.

jimdempseyatthecove
Black Belt
151 Views

Did you add extern "C" to the function?

Jim Dempsey

Jason_B_
Beginner
134 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).

Reply