1

我有一组使用 make -j 命令在不同机器上编译的 c++ 文件。仅当我将 pgi 编译器与并行 make 一起使用时才会出现问题,某些文件出现以下错误(此特定错误适用于atprop.cpp文件):

    /opt/share/gcc/4.6.0/el6/bin/ld: error in atprop.o(.eh_frame); no .eh_frame_hdr table will be created.
    /opt/share/gcc/4.6.0/el6/bin/ld: atprop.o: invalid string offset 615811912 >= 1421 for section `.strtab'
    /opt/share/gcc/4.6.0/el6/bin/ld: final link failed: Nonrepresentable section on output

然后我意识到这个错误发生在与许多可执行目标相关的源文件中。例如atprop.cpp使用我在代码中使用的不同宏(无宏、-DUBC、-DVBC)编译了三次。这是 Makefile 中与atprop.cpp相关的部分

    $(B)/atprop: $(S)/atprop.cpp  $(O)/atlib.o $(O)/atwave.o $(O)/atvecop.o
            $(CPPC) $(S)/atprop.cpp $(O)/atlib.o $(O)/atwave.o $(O)/atvecop.o -o $@ $(INC)  $(FLAGSET2)

    $(B)/atprop_ubc: $(S)/atprop.cpp  $(O)/atlib.o $(O)/atwave.o $(O)/atvecop.o
            $(CPPC) $(S)/atprop.cpp $(O)/atlib.o $(O)/atwave.o $(O)/atvecop.o -o $@ $(INC)  $(FLAGSET2) -DUBC

    $(B)/atprop_vbc: $(S)/atprop.cpp  $(O)/atlib.o $(O)/atwave.o $(O)/atvecop.o
            $(CPPC) $(S)/atprop.cpp $(O)/atlib.o $(O)/atwave.o $(O)/atvecop.o -o $@ $(INC)  $(FLAGSET2) -DVBC

变量 $(CPPC)=mpic++ 等于 PGI 编译器的 MPI 包装器的路径。

    $ mpic++ --version

    pgcpp 12.10-0 64-bit target on x86-64 Linux -tp bulldozer 
    Copyright 1989-2000, The Portland Group, Inc.  All Rights Reserved.
    Copyright 2000-2012, STMicroelectronics, Inc.  All Rights Reserved.

请注意,如果我使用串行 make(即不带 -j 选项的 make),编译运行顺利,没有问题。

我认为这是问题所在:PGI 编译器创建了一个与源文件同名的临时目标文件(对于上面的示例atprop.o。如果并行运行,使用不同宏的编译将全部写入同一个目标文件,这会导致我上面提到的问题。

这只发生在 PGI 编译器上,当我使用 intel 或 gnu 编译器时,我不会遇到这个问题。所以我的问题是我可以做些什么来缓解 PGI 编译器的这个问题?请记住,我有很多具有相同问题的 c++ 文件,并且我试图避免对 Makefile 进行重大修改。

4

2 回答 2

1

To determine if your guess about what the PGI compiler is doing is correct, you can try running it (by hand from the command line) using strace, perhaps with the -ff and -o flags, and look to see what files it creates.

If you determine that it is this problem, the first thing you should do is look through the PGI documentation and/or ask on their support forums to see if there are compiler options you can add that will change this behavior, or environment variables you can set.

If none of that works, you're in a world of hurt. A simple answer would be to change your make rules to copy the source to a unique name before compiling, but that destroys the ability to debug it (since the source file encoded by the debugger will be some random filename). Any change I can think of would involve very significant changes to your makefiles (for example, adding order-only prerequisites to the rules where multiple files are built from the same source).

It's too bad that your makefiles appear to be simply long lists of explicit rules; if you were using a smaller number of implicit rules instead it would be easier to fix the makefiles.

于 2013-12-18T12:41:14.220 回答
1

为了快速解决问题,我在 Makefile 中的目标之间建立了虚假的依赖关系。这样我可以避免同时编译相同的源文件(针对不同的目标)。

于 2014-01-04T14:09:15.247 回答