Undefined references with pgf90 and "-acc" option

I have a relatively complex Fortran 2003 code that I would like to compile with the
PGI Community Edition Version 19.10 in view of exploiting OpenACC pragmas.
In the current version of the code, such pragmas are inexistent.

This code compiles and links well when I don’t include the option “-acc”.

When I add the “-acc” option to the other options (“-fast -Minfo=all -Kieee -Mr8 -Mr8intrinsics”), I am
getting an error in the link phase:
nvlink error : Undefined reference to ‘_reference_cells_21’ in ‘CMakeFiles/mesh_partitionningTest.dir/mesh_partitionningTest.f90.o’
pgacclnk: child process exit status 2: /home/lanteri/opt/pgi/linux86-64-llvm/19.10/bin/pgnvd
make[2]: *** [bin/mesh_partitionningTest] Erreur 2
make[1]: *** [tst/mesh_partitionning/CMakeFiles/mesh_partitionningTest.dir/all] Erreur 2
make: *** [all] Erreur 2

The mesh_partitionningTest.f90 executable is actually linked with a library of modules.
When I use the “nm” command on this library and look for the “reference_cells” occurences, I obtain:
00000000001f9080 T reference_cells_
000000000047f040 B reference_cells_0
0000000000489380 B reference_cells_2
0000000000449980 D reference_cells_21
0000000000481c00 B reference_cells_8

When I remove the “-acc” option, the occurrences are:
00000000004620c0 B reference_cells_0
0000000000440a00 D reference_cells_10
000000000046c400 B reference_cells_2
0000000000464c80 B reference_cells_8

It seems that the “expected” underscore at the end of the reference has been removed
when using the “-acc” option.

Thanks in advance for your help!

Hi sl06,

This look to me like “reference_cells_21” is an initialized variable found in the “reference_cells” module. Module variables have global storage on the host.

Given the error is coming from the device linker (nvlink), you’re most likely referencing this module variable in device code but haven’t created a device copy of the variable via the “!$acc declare copyin” directive.

Granted, I would have expected the compiler to give an error during compilation stating that the host variable can’t be used in device code if this were the case, so something else may be happening.

The mesh_partitionningTest.f90 executable is actually linked with a library of modules.

I’m not sure what you mean by a “library of modules”. Do you mean that you’ve created a library from the objects which correspond the module files? If so, are you using a static (.a) or shared library (.so)?

If it’s static, then nvlink should be able to find the reference in the library provided you include the library on the link. Though order might matter in this case, so you might try adjusting where the library appears on the link line.

However if you’re using a shared object, then this could be the source of the error. Shared objects aren’t linked until load, and there’s no dynamic linker (like ldd) for device code. While device code can be included in shared objects, the device module variable would only be accessible within the shared object itself. Hence here, you must link in the module’s object file statically.

Granted, these are all just educated guesses, so if none of these situations apply, can you please provide more details on the structure of your program and how you’ve added the OpenACC directives. Also, if you’re able, a reproducing example would be appreciated.

Note that “nm” will only show you host references, not device references.

Hope this helps,
Mat

Hi Mat,

I have solved the problem by following your advice and linked to a static library.

Thanks!