Question

I'm working on an DNA Fragment Assembly program. The CPU-only version is built in C language using GCC and I'm trying to build a GPU version using NVCC.

Here is the makefile

all : clean FragmentAssembly.exe

FragmentAssembly.exe : Common.o Fragment.o ILS.o Consensus.o main.o
    nvcc -pg -o FragmentAssembly.exe Common.o Fragment.o ILS.o Consensus.o main.o 

Common.o : Common.cu
    nvcc -pg -o Common.o -c Common.cu

Fragment.o : Fragment.cu
    nvcc -pg -o Fragment.o -c Fragment.cu

ILS.o : ILS.cu
    nvcc -pg -o ILS.o -c ILS.cu

Consensus.o : Consensus.cu
    nvcc -pg -o Consensus.o -c Consensus.cu

main.o : main.cu
    nvcc -pg -o main.o -c main.cu

clean : 
    rm -f *.exe *.o

As seen, the original .c files became .cu files for nvcc to compile them correctly. All of the cu files contain includes of their corresponding files (Common.h for Common.cu, etc..) except for main.cu.

ILS.h contians definition of global variables p_instanceFragments and p_instanceLength

The problem is when compiling NVCC, for an unknown reason, I get the following errors :

Consensus.o:(.bss+0x0): multiple definition of `p_instanceFragments'
ILS.o:(.bss+0x0): first defined here
Consensus.o:(.bss+0x8): multiple definition of `p_instanceLength'
ILS.o:(.bss+0x8): first defined here

There is no real multiple definitions since the same code is built correctly using GCC. It looks as if ILS.h is getting included twice in nvcc, by ILS.cu and Consensus.cu. This is also not possible since I've wrapped all my header files with an #ifndef .. #define .. #endif statements to avoid multiple includes and infinite include loops.

Maybe something with the makefile commands ? or should I use gcc for linking ? Can you tell me how to deal with it ?

Regards,

Was it helpful?

Solution

After discussion: Here a description of what happened:

If you use gcc and you have two files (lets say f1.c and f2.c), and in both files you declare:

int myGlobalVariable;

Then the following will happen:

  • When compiling f1.c into f1.o, the object file will reserve space for myGlobalVariable.
  • When compiling f2.c into f2.o, the object file will also reserve space for myGlobalVariable.
  • When you link both object files together, the linker will detect that there are two variables called myGlobalVariable and will merge these variables together.

Now it seems the nvcc compiler/linker is not able to merge these variables.

The problem was, that the file ILS.h declares <some type> p_instanceFragments;. Because ILS.h is included into both ILS.cu and Consensus.cu, you get this variable twice and nvcc complains when it has to link the application.

The solution is to declare extern <some type> p_instanceFragments; in ILS.h and then to define <some type> p_instanceFragments; either in ILS.cu or Consensus.cu (not in both).

The question What are extern variables in C has a rather extensive answer explaining all of this in detail.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top