как скомпилировать MPI и не-MPI версии одной и той же программы с automake?
у меня есть код C++, который может быть скомпилирован с поддержкой MPI в зависимости от определенный флаг препроцессора; отсутствует соответствующий флаг, источники компиляция в непараллельную версию.
Я хотел бы настроить Makefile.am так, что он компилирует и в
MPI-параллель и последовательная версия, если опция
./configure
дается.
вот уловка: MPI имеет свою собственную оболочку компилятора C++ и настаивает что исходники компилируются и связанный, используя его, а не стандарт Компилятор C++. Если бы я сам написал Makefile, мне пришлось бы сделайте что-нибудь вроде этого:
myprog.seq: myprog.cxx
$(CXX) ... myprog.cxx
myprog.mpi: myprog.cxx
$(MPICXX) -DWITH_MPI ... myprog.cxx
есть ли способ сказать automake, что он должен использовать $(MPICXX) вместо этого $(CXX) при компиляции версии программы с поддержкой MPI?
6 ответов
у меня такая же проблема, и я обнаружил, что нет действительно хорошего способа получить autotools в условно используйте компиляторы MPI для определенных целей. Autotools хорошо разбирается в том, какой компилятор использовать на основе языка, на котором написан ваш источник (CC
, CXX
, FC
, F77
, etc.), но на самом деле не очень хорошо понять, использовать ли компилятор MPI для определенной цели. Вы можете установить MPICC, MPICXX и т. д. но вы по сути переписать все правила Makefile для вашей цели (как вы сделали выше), если вы используете компилятор таким образом. Если вы это сделаете, какой смысл писать файл automake?
кто-то еще предложил использовать MPI как внешнюю библиотеку, и это подход, который я бы рекомендовал, но вы не должны делать это вручную, потому что разные установки MPI имеют разные наборы флагов, которые они передают компилятору, и они могут зависеть от языка, который вы компилируете.
хорошая вещь это все компиляторы MPI, которые я знаю, поддерживают аргументы интроспекции, такие как -show
, -show-compile
или -show-link
. Вы можете автоматически извлекать аргументы из сценариев.
Итак, то, что я сделал, чтобы справиться с этим, было сделать m4
сценарий, который извлекает определяет, включает, пути библиотеки, libs и флаги компоновщика из компиляторов MPI, а затем назначает их переменным, которые вы можете использовать в своем Makefile.am
. Вот сценарий:
это делает MPI работать так, как automake ожидает его. Кстати, именно такой подход CMake использует в своих FindMPI
модуль, и я нахожу это довольно хорошо работает. Это делает сборку намного удобнее, потому что вы можете просто сделать что-то подобное для своих целей:
bin_PROGRAMS = mpi_exe seq_exe
# This is all you need for a sequential program
seq_exe_SOURCES = seq_exe.C
# For an MPI program you need special LDFLAGS and INCLUDES
mpi_exe_SOURCES = mpi_exe.C
mpi_exe_LDFLAGS = $(MPI_CXXLDFLAGS)
INCLUDES = $(MPI_CXXFLAGS)
существуют аналогичные флаги для других языков, так как, как я уже сказал, конкретные флаги и библиотеки могут зависит от используемого компилятора MPI языка.
lx_find_mpi.m4
также устанавливает некоторые переменные оболочки, чтобы вы могли проверить в своем configure.ac
файл, был ли найден MPI. например, если вы ищете поддержку MPI c++, вы можете проверить $have_CXX_mpi
чтобы узнать, нашел ли его макрос.
я протестировал этот макрос с mvapich и openmpi с, а также на заказ MPICH2 реализация на BlueGene машины (хотя он не решает все проблемы кросс-компиляции, которые вы увидите там). Дайте мне знать, если что-то не работает. Я хотел бы сохранить макрос как можно более надежным.
мне жаль, что использование MPI automake так сложно. Я боролся с этим в течение многих месяцев пытается найти хорошее решение. У меня есть исходное дерево, в котором есть одна библиотека, а затем много программ в подпапках, которые используют библиотеку. Некоторые из папок являются программами mpi, но когда я пытаюсь заменить CXX компилятором MPI, используя in Makefile.am
.
if USE_MPI
MPIDIR = $(MPICOMPILE)
MPILIB = $(MPILINK)
CXX=@MPICXX@
F77=@MPIF77@
MPILIBS=$(MPILINK)
endif
Я
CXX was already defined in condition TRUE, which includes condition USE_MPI ...
configure.ac:12: ... `CXX' previously defined here
у меня нет правила, которое указывает компилятор, поэтому, возможно, есть способ сделать это.
SUBDIRS = .
bin_PROGRAMS = check.cmr
check_ccmr_SOURCES = check_gen.cpp
check_ccmr_CXXFLAGS = -I$(INCLUDEDIR) $(MPIDIR)
check_ccmr_LDADD = -L$(LIBDIR)
check_ccmr_LDFLAGS = $(MPILIB)
если вы отключили до automake
, что-то вроде этого может сработать:
настройка.ac:
AC_ARG_ENABLE([seq], ...)
AC_ARG_ENABLE([mpi], ...)
AM_CONDITIONAL([ENABLE_SEQ], [test $enable_seq = yes])
AM_CONDITIONAL([ENABLE_MPI], [test $enable_mpi = yes])
AC_CONFIG_FILES([Makefile seq/Makefile mpi/Makefile])
make-файл.ам:
SUBDIRS =
if ENABLE_SEQ
SUBDIRS += seq
endif
if ENABLE_MPI
SUBDIRS += mpi
endif
источники.am:
ALL_SOURCES = src/foo.c src/bar.cc src/baz.cpp
сл/make-файл.ам:
include $(top_srcdir)/sources.am
bin_PROGRAMS = seq
seq_SOURCES = $(ALL_SOURCES)
ЛПУ/make-файл.ам:
include $(top_srcdir)/sources.am
CXX = $(MPICXX)
AM_CPPFLAGS = -DWITH_MPI
bin_PROGRAMS = mpi
mpi_SOURCES = $(ALL_SOURCES)
единственное, что мешает вам делать оба из них в одном каталоге, это переопределение $(CXX)
. Вы могли бы, например,mpi_CPPFLAGS
и automake
будет обработайте это изящно,но переключатель компилятора делает его здесь невозможным.
возможным обходным путем для не использования различных источников может быть:
myprog.seq: myprog.cxx
$(CXX) ... myprog.cxx
myprog-mpi.cxx: myprog.cxx
@cp myprog.cxx myprog-mpi.cxx
myprog.mpi: myprog-mpi.cxx
$(MPICXX) -DWITH_MPI ... myprog-mpi.cxx
@rm -f myprog-mpi.cxx
для Automake:
myprog-bin_PROGRAMS = myprog-seq myprog-mpi
myprog_seq_SOURCES = myprog.c
myprog-mpi.c: myprog.c
@cp myprog.c myprog-mpi.c
myprog_mpi_SOURCES = myprog-mpi.c
myprog_mpi_LDFLAGS = $(MPI_CXXLDFLAGS)
INCLUDES = $(MPI_CXXFLAGS)
BUILT_SOURCES = myprog-mpi.c
CLEANFILES = myprog-mpi.c
вот решение, которое я придумал для создания двух статических библиотек-одной с MPI (libmylib_mpi.a
) и один без (libmylib.a
). Преимущество этого метода заключается в том, что нет необходимости дублировать исходные файлы в один файл Makefile.я за оба варианта, и возможность использовать подкаталоги. Вы должны иметь возможность изменять это по мере необходимости для создания двоичного файла вместо библиотеки. Я создаю библиотеку без MPI как обычно, а затем для варианта MPI я оставляю _SOURCES
пустая и использовать , указание расширения .mpi.o
для объектных файлов. Затем я указываю правило для создания объектных файлов MPI с помощью компилятора MPI.
общая структура файлов / каталогов-это что-то вроде
configure.ac
Makefile.am
src
mylib1.cpp
mylib2.cpp
...
include
mylib.h
...
настройка.ac:
AC_INIT()
AC_PROG_RANLIB
AC_LANG(C++)
AC_PROG_CXX
# test for MPI, define MPICXX, etc. variables, and define HAVE_MPI as a condition that will evaluate to true if MPI is available and false otherwise.
AX_MPI([AM_CONDITIONAL([HAVE_MPI], [test "1" = "1"])],[AM_CONDITIONAL([HAVE_MPI], [test "1" = "2"])]) #MPI optional for xio
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
вероятно, есть более эффективный способ сделать условную проверку, чем я перечислил здесь (я приветствую предложения).
make-файл.ам:
AUTOMAKE_OPTIONS = subdir-objects
lib_LIBRARIES = libmylib.a
libmylib_a_SOURCES = src/mylib_1.cpp src/mylib_2.cpp ...
#conditionally generate libmylib_mpi.a if MPI is available
if HAVE_MPI
lib_LIBRARIES += libmylib_mpi.a
libmylib_mpi_a_SOURCES = #no sources listed here
#use LIBADD to specify objects to add - use the basic filename with a .mpi.o extension
libmylib_mpi_a_LIBADD = src/mylib_1.mpi.o src/mylib_2.mpi.o ...
endif
AM_CPPFLAGS = -I${srcdir}/include
include_HEADERS = include/mylib.h
# define a rule to compile the .mpi.o objects from the .cpp files with the same name
src/%.mpi.o: ${srcdir}/src/%.cpp ${srcdir}/include/mylib.h
$(MPICXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DWITH_MPI=1 -c $(patsubst %.mpi.o,$(srcdir)/%.cpp,$@) -o $@
#define a rule to clean the .mpi.o files
clean-local:
-rm -f src/*.mpi.o
установки MPI (обычно) поставляются с оболочками компилятора, но нет требования, чтобы вы их использовали -- MPI does не настаивать на этом. Если вы хотите пойти своим путем, вы можете написать свой собственный makefile, чтобы убедиться, что компилятор C++ получает правильные библиотеки (и т. д.). Чтобы выяснить, что такое правильные библиотеки (etc), проверьте оболочку компилятора, которая во всех системах, которые я использовал, является скриптом оболочки.
на первый взгляд обертки компилятора, которые поставляются с такие продукты, как компиляторы Intel, немного сложны, но остановитесь и подумайте о том, что происходит-вы просто компилируете программу, которая использует внешнюю библиотеку или две. Написать makefile для использования библиотек MPI не сложнее, чем написать makefile для использования любой другой библиотеки.