문제

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,

도움이 되었습니까?

해결책

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top