11

特定のプリプロセッサフ​​ラグに応じて、MPIサポートを使用してコンパイルできるC++コードがあります。適切なフラグがない場合、ソースは非並列バージョンにコンパイルされます。

オプションが指定されている場合は 、MPIパラレルバージョンとシーケンシャルバージョンの両方をコンパイルするようにMakefile.amをセットアップしたいと思います。./configure

キャッチは次のとおりです。MPIには独自のC++コンパイララッパーがあり、ソースは標準のC++コンパイラではなくそれを使用してコンパイルおよびリンクされると主張しています。Makefileを自分で作成する場合は、次のようにする必要があります。

myprog.seq: myprog.cxx
    $(CXX) ... myprog.cxx

myprog.mpi: myprog.cxx
    $(MPICXX) -DWITH_MPI ... myprog.cxx

プログラムのMPI対応バージョンをコンパイルするときに、$(CXX)ではなく$(MPICXX)を使用する必要があることをautomakeに通知する方法はありますか?

4

6 に答える 6

7

私も同じ問題を抱えており、autotoolsで特定のターゲットにMPIコンパイラを条件付きで使用するための本当に良い方法がないことがわかりました。CCAutotoolsは、ソースが記述されている言語( 、、、、など)CXXに基づいて使用するコンパイラーを判断するのは得意ですが、特定のターゲットにMPIコンパイラーを使用するかどうかを判断するのは得意ではありません。MPICC、MPICXXなどを設定できますが、コンパイラをこのように使用する場合は、基本的に、ターゲットのすべてのMakefileルールを(上記で行ったように)書き直す必要があります。そうすると、automakeファイルを書く意味は何ですか?FCF77

他の誰かが外部ライブラリのようにMPIを使用することを提案しました。これは私が提唱するアプローチですが、MPIのインストールが異なれば、コンパイラに渡すフラグのセットも異なり、依存する可能性があるため、手動で行うべきではありません。コンパイルしている言語。

良いことは、私が知っている現在出荷されているすべてのMPIコンパイラが、、、などのイントロスペクション引数をサポートしている-showこと-show-compileです-show-link。スクリプトから引数を自動的に抽出できます。

したがって、これに対処するために私が行ったm4のは、MPIコンパイラから定義、インクルード、ライブラリパス、ライブラリ、およびリンカーフラグを抽出し、で使用できる変数にそれらを割り当てるスクリプトを作成することでしたMakefile.am。スクリプトは次のとおりです。

lx_find_mpi.m4

これにより、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.m4configure.acまた、 MPIが見つかったかどうかをファイルでテストできるように、いくつかのシェル変数を設定します。たとえば、MPI C ++サポートを探している$have_CXX_mpi場合は、マクロがそれを検出したかどうかをテストできます。

このマクロをmvapichOpenMPI 、およびBlueGeneマシンでのカスタムMPICH2実装でテストしました(ただし、そこに表示されるすべてのクロスコンパイルの問題に対処しているわけではありません)。何かがうまくいかない場合は教えてください。マクロをできるだけ堅牢に保ちたいです。

于 2010-10-19T21:13:10.683 に答える
5

automakeにMPIを使用させるのは非常に難しいことをお詫び申し上げます。私はこれに何ヶ月も苦労して、良い解決策を見つけようとしています。1つのライブラリと、そのライブラリを使用するサブフォルダ内の多くのプログラムを持つソースツリーがあります。一部のフォルダはmpiプログラムですが、CXXをで使用しているMPIコンパイラに置き換えようとすると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)
于 2012-07-26T19:58:38.440 に答える
2

subdir-objectsのオプションを無効にしている場合はautomake、次のように機能する可能性があります。

configure.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])

Makefile.am:

SUBDIRS =
if ENABLE_SEQ
SUBDIRS += seq
endif
if ENABLE_MPI
SUBDIRS += mpi
endif

sources.am:

ALL_SOURCES = src/foo.c src/bar.cc src/baz.cpp

seq / Makefile.am:

include $(top_srcdir)/sources.am

bin_PROGRAMS = seq
seq_SOURCES = $(ALL_SOURCES)

mpi / Makefile.am:

include $(top_srcdir)/sources.am

CXX = $(MPICXX)
AM_CPPFLAGS = -DWITH_MPI

bin_PROGRAMS = mpi
mpi_SOURCES = $(ALL_SOURCES)

同じディレクトリでこれらの両方を実行できないようにする唯一のことは、のオーバーライドです$(CXX)。たとえば、それを適切に設定mpi_CPPFLAGSしてautomake処理することはできますが、コンパイラスイッチを使用すると、ここでは使用できなくなります。

于 2010-10-19T20:52:37.850 に答える
1

異なるソースを使用しない場合の考えられる回避策は次のとおりです。

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
于 2011-01-14T17:39:05.283 に答える
1

これが、2つの静的ライブラリを構築するために私が思いついた解決策です。1つはMPI(libmylib_mpi.a)を使用し、もう1つは()を使用しませlibmylib.aん。この方法の利点は、重複するソースファイル、両方のバリアントに対して単一のMakefile.amが不要であり、サブディレクトリを使用できることです。ライブラリの代わりにバイナリを生成するために、必要に応じてこれを変更できるはずです。通常どおり非MPIライブラリを構築し、MPIバリアントの場合は_SOURCES空のままにして、代わりにオブジェクトファイル_LIBADDの拡張子を指定して使用します。.mpi.o次に、MPIコンパイラを使用してMPIオブジェクトファイルを生成するルールを指定します。

全体的なファイル/ディレクトリ構造は次のようなものです

configure.ac
Makefile.am
src
    mylib1.cpp
    mylib2.cpp
    ...
include
    mylib.h
    ...

configure.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

ここにリストしたよりも、おそらくより効率的な条件付きチェックの方法があります(提案を歓迎します)。

Makefile.am:

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
于 2017-10-15T20:04:47.463 に答える
0

MPIインストールには(通常)コンパイララッパーが付属していますが、それらを使用する必要はありませ。MPIはそれを要求しません。独自の方法で実行したい場合は、独自のmakefileを記述して、C ++コンパイラが適切なライブラリ(など)を取得できるようにすることができます。適切なライブラリ(など)が何であるかを理解するには、使用したすべてのシステムでシェルスクリプトであるコンパイララッパーを調べます。

一見すると、Intelコンパイラなどの製品に付属しているコンパイララッパーは少し気が遠くなりますが、何が起こっているのかを考えてみてください。外部ライブラリを1つか2つ使用するプログラムをコンパイルしているだけです。MPIライブラリを使用するためのmakefileの作成は、他のライブラリを使用するためのmakefileの作成と同じくらい難しくありません。

于 2010-10-19T13:26:20.433 に答える