2010-10-19 27 views
11

Tôi có một mã C + + có thể được biên dịch với sự hỗ trợ của MPI tùy thuộc vào một lá cờ tiền xử lý nhất định ; thiếu cờ thích hợp, các nguồn biên dịch thành phiên bản không song song.làm thế nào để biên dịch MPI và phiên bản không MPI của cùng một chương trình với automake?

Tôi muốn thiết lập Makefile.am để nó biên dịch cả các MPI-song song phiên bản tuần tự, nếu một tùy chọn để ./configure được đưa ra.

Đây là điểm bắt: MPI có trình bao bọc trình biên dịch C++ của riêng nó và nhấn mạnh nguồn được biên dịch và liên kết bằng cách sử dụng nó thay vì trình biên dịch C++ tiêu chuẩn . Nếu tôi được viết Makefile bản thân mình, tôi sẽ phải làm điều gì đó như thế này:

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

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

Có cách nào để nói với automake rằng nó phải sử dụng $ (MPICXX) thay vì của $ (CXX) khi biên dịch phiên bản cho phép của chương trình MPI?

+1

Bạn có quan tâm nếu chương trình nối tiếp được liên kết chống lại các thư viện MPI trong "xây dựng cả hai" trường hợp? Nếu không, bạn chỉ có thể sử dụng mpicxx cho cả hai - nó không giống như nó sẽ làm tổn thương bất cứ điều gì. Và nếu bạn không xây dựng phiên bản mpi, bạn có thể đặt sử dụng g ++ cho mọi thứ. Theo kinh nghiệm, đây là những gì mà rất nhiều gói có cả hai phiên bản song song và nối tiếp dường như làm - hdf5 đến với tâm trí. –

+0

Nói chung, không, và tôi đã sử dụng để biên dịch theo cách này. Tôi phát triển một số công cụ PMPI, và nói chung bạn không muốn liên kết một thư viện đánh chặn với MPI, mà bạn buộc phải làm nếu bạn biên dịch với mpicc. – tgamblin

Trả lời

7

Tôi có cùng một vấn đề và tôi thấy rằng không có cách nào thực sự tốt để tự động nhận được tự động có điều kiện sử dụng trình biên dịch MPI cho các mục tiêu cụ thể.Autotools có ích khi tìm ra trình biên dịch nào sử dụng dựa trên ngôn ngữ mà nguồn của bạn được viết bằng (CC, CXX, FC, F77, v.v.), nhưng thực sự không giỏi để tìm hiểu xem có sử dụng trình biên dịch MPI hay không một mục tiêu cụ thể. Bạn có thể thiết lập MPICC, MPICXX, vv, nhưng về cơ bản bạn phải viết lại tất cả các quy tắc Makefile cho mục tiêu của mình (như bạn đã làm ở trên) nếu bạn sử dụng trình biên dịch theo cách này. Nếu bạn làm điều đó, điểm viết một tập tin tự động là gì?

Người khác đề xuất sử dụng MPI như thư viện bên ngoài và đây là cách tiếp cận tôi ủng hộ, nhưng bạn không nên làm điều đó bằng tay, bởi vì các cài đặt MPI khác nhau có các bộ cờ khác nhau mà chúng chuyển đến trình biên dịch và chúng có thể phụ thuộc vào ngôn ngữ bạn đang biên soạn.

Điều tốt là tất cả các trình biên dịch MPI hiện đang vận chuyển mà tôi biết về các đối số introspection hỗ trợ, như -show, -show-compile hoặc -show-link. Bạn có thể tự động trích xuất các đối số từ các tập lệnh. Vì vậy, những gì tôi đã làm để đối phó với điều này là để thực hiện một tập lệnh m4 trích xuất các định nghĩa, bao gồm, đường dẫn thư viện, libs và cờ liên kết từ trình biên dịch MPI, sau đó gán chúng cho các biến bạn có thể sử dụng trong Makefile.am của bạn . Đây là tập lệnh:

lx_find_mpi.m4

Điều này làm cho MPI hoạt động theo cách tự động mong đợi. Ngẫu nhiên, đây là cách tiếp cận CMake sử dụng trong mô-đun FindMPI của họ và tôi thấy nó hoạt động khá tốt ở đó. Nó làm cho việc xây dựng nhiều thuận tiện hơn vì bạn chỉ có thể làm điều gì đó như thế này cho các mục tiêu của bạn:

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) 

Có cờ tương tự cho các ngôn ngữ khác từ đó, như tôi đã nói, những lá cờ nói riêng và các thư viện có thể khác nhau tùy thuộc vào trình biên dịch MPI của ngôn ngữ mà bạn sử dụng.

lx_find_mpi.m4 cũng đặt một số biến trình bao để bạn có thể kiểm tra trong tệp configure.ac cho dù có tìm thấy MPI hay không. ví dụ: nếu bạn đang tìm kiếm hỗ trợ MPI C++, bạn có thể kiểm tra $have_CXX_mpi để xem macro có tìm thấy nó hay không.

Tôi đã thử nghiệm macro này với mvapichOpenMPI, cũng như triển khai MPICH2 tùy chỉnh trên BlueGene máy (mặc dù nó không giải quyết tất cả các vấn đề biên dịch chéo bạn sẽ thấy ở đó). Hãy cho tôi biết nếu một cái gì đó không hoạt động. Tôi muốn giữ macro càng mạnh càng tốt.

+0

Bạn nên thêm nó vào LDADD thay vì LDFLAGS nếu không một số liên kết sẽ ném lỗi. Và kịch bản thực tế có lỗi: với sed, để loại bỏ dấu cách bạn nên sử dụng sed/+// g thay vì sed/*// g. – w00d

+0

Macro của bạn chạy tốt cho tôi. Tuy nhiên, tôi phải chạy nó hai lần để có được cả hai giá trị từ MPICC và MPICXX. Trong lần gọi thứ hai, tôi bọc macro giữa 'AC_LANG_PUSH ([C++])' và 'AC_LANG_POP ([C++])'. Cảm ơn SW. – r3x

0

Cài đặt MPI thực hiện (thường) gửi kèm với trình bao bọc trình biên dịch, nhưng không yêu cầu bạn sử dụng chúng - MPI thực hiện không phải nhấn mạnh vào nó. Nếu bạn muốn đi theo cách riêng của bạn, bạn có thể viết makefile của riêng bạn để đảm bảo rằng trình biên dịch C++ được các thư viện đúng (vv). Để tìm ra những thư viện thích hợp (etc) là gì, hãy kiểm tra trình bao bọc trình biên dịch, trên tất cả các hệ thống mà tôi đã sử dụng, một kịch bản lệnh shell. Ngay từ cái nhìn đầu tiên, trình bao bọc trình biên dịch với các sản phẩm như trình biên dịch Intel hơi khó khăn nhưng dừng lại và suy nghĩ về những gì đang diễn ra - bạn đơn giản biên dịch một chương trình sử dụng thư viện bên ngoài hoặc hai. Viết một makefile để sử dụng các thư viện MPI không khó hơn việc viết một makefile để sử dụng bất kỳ thư viện nào khác.

+0

Cảm ơn câu trả lời của bạn. Mặc dù không yêu cầu tôi sử dụng trình biên dịch trình biên dịch MPI, có nhiều triển khai MPI ở đó và mỗi cái sử dụng tên thư viện riêng của nó, v.v. - Tôi muốn viết lại một đoạn trích Makefile để sử dụng $ (MPICXX) hơn là duy trì một vài dòng mã automake/autoconf để cung cấp CPPFLAGS/LDFLAGS/LIBS cho mỗi phiên bản MPI ngoài kia ... –

+0

Sẽ không khó khăn hơn nếu tất cả những gì bạn quan tâm là * một nền tảng *. Tuy nhiên, tôi chạy trên 3 hoặc 4 kiến ​​trúc cụm khác nhau, và trong khi tất cả chúng đều chia sẻ một trình biên dịch mpicc, các cờ và thư viện cụ thể cho nền tảng khác nhau, tốt, khác nhau. Bạn không thể làm điều này một cách hợp lý trừ khi bạn nhìn vào các trình bao bọc trong một kịch bản, đó là những gì tôi khuyên bạn nên làm. Xem câu trả lời của tôi. – tgamblin

2

Nếu bạn đã vô hiệu hóa tùy chọn subdir-objects-automake, một cái gì đó như thế này có thể làm việc:

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) 

Điều duy nhất ngăn cản bạn từ làm cả hai trong cùng thư mục là ghi đè $(CXX). Ví dụ, bạn có thể đặt mpi_CPPFLAGSautomake sẽ xử lý điều đó một cách duyên dáng, nhưng trình chuyển đổi trình biên dịch làm cho nó trở thành không có ở đây.

+0

Downvote sans bình luận. Lam tôt lăm. Tôi sẽ cho rằng đó là một chút của một hack bẩn, nhưng bạn có một ý tưởng tốt hơn? –

+0

+1 để chống lại -1 giây bình luận –

1

Một cách giải quyết có thể cho không sử dụng các nguồn khác nhau có thể là:

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 

cho 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 
+0

Giải pháp thông minh, cảm ơn! Tôi nghĩ có một lỗi đánh máy: dòng 'myprog ..._ SOURCES' thứ hai nên đọc' myprog_mpi_SOURCES = myprog-mpi.c' và sau đó là 'mpyorog_mpi_LDFLAGS = ...' –

+0

Có, cảm ơn. Tôi đã sửa mã! :) –

+0

Bạn cũng phải liệt kê myprog-mpi.c như được tạo tự động bằng cách sử dụng 'BUILT_SOURCES = myprog-mpi.c'. – user562374

4

Tôi xin lỗi rằng có automake sử dụng MPI là rất khó khăn. Tôi đã đấu tranh với điều này trong nhiều tháng cố gắng tìm một giải pháp tốt. Tôi có một cây nguồn có một thư viện và sau đó nhiều chương trình trong các thư mục con sử dụng thư viện. Một số thư mục là các chương trình mpi, nhưng khi tôi cố gắng thay thế CXX bằng trình biên dịch MPI bằng cách sử dụng trong Makefile.am.

if USE_MPI 
    MPIDIR = $(MPICOMPILE) 
    MPILIB = $(MPILINK) 
    [email protected]@ 
    [email protected]@ 
    MPILIBS=$(MPILINK) 
endif 

tôi nhận được

CXX was already defined in condition TRUE, which includes condition USE_MPI ... 
configure.ac:12: ... `CXX' previously defined here 

Tôi không có một quy tắc chỉ định trình biên dịch, vì vậy có lẽ có một cách để làm điều đó.

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) 
1

Dưới đây là giải pháp mà tôi đã đưa ra để xây dựng một hai thư viện tĩnh - một với Bộ KH & ĐT (libmylib_mpi.a) và một không có (libmylib.a). Ưu điểm của phương pháp này là không cần các tệp nguồn trùng lặp, một Makefile.am duy nhất cho cả hai biến thể và khả năng sử dụng các subdir. Bạn sẽ có thể sửa đổi điều này khi cần thiết để tạo ra một tệp nhị phân thay vì một thư viện. Tôi xây dựng thư viện non-MPI như bình thường, sau đó cho biến thể MPI, tôi để trống _SOURCES và sử dụng _LIBADD thay vào đó, chỉ định phần mở rộng là .mpi.o cho các tệp đối tượng. Sau đó tôi xác định một quy tắc để tạo ra các tệp đối tượng MPI bằng trình biên dịch MPI.

Nhìn chung tập tin/cấu trúc thư mục là một cái gì đó giống như

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 

Có lẽ là một cách hiệu quả hơn để làm việc kiểm tra điều kiện hơn tôi đã liệt kê ở đây (tôi m chào mừng bạn đến với đề xuất).

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,[email protected]) -o [email protected] 

#define a rule to clean the .mpi.o files 
clean-local: 
    -rm -f src/*.mpi.o 
Các vấn đề liên quan