Заголовок с предварительной декларацией MPI - PullRequest
0 голосов
/ 22 октября 2019

Я использую короткую оболочку MPI, например, такую:

#ifndef INC_MyLib_MPIWRAPPER_H
#define INC_MyLib_MPIWRAPPER_H

#include <mpi.h>


/* libMyLib MPI struct & macros */
namespace libMyLib{
    extern int mpi_rank;
    extern int mpi_nranks;
    extern int mpi_msg;
    extern int mpi_msg_;
    extern MPI_Comm mpi_active_comm;
}

#define MPI_INIT MPI_Init(&argc, &argv); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_INIT_NULL MPI_Init(nullptr, nullptr); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_FINISH MPI_Finalize( );

#define MPI_INTERRUPT libMyLib::mpi_msg = 1; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);
#define MPI_ERROR_CHECK libMyLib::mpi_msg = 0; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);; if( libMyLib::mpi_msg_ > 0 ){throw std::runtime_error(" eror " );}

#endif //INC_MyLib_MPIWRAPPER_H

Я бы хотел избавиться от зависимости mpi.h здесь, поэтому я попытался добавить предварительное объявление типов MPIвот так:

#ifndef INC_MyLib_MPIWRAPPER_H
#define INC_MyLib_MPIWRAPPER_H

#include <mpi.h>

/* MPI forward declarations to remove MPI header dependency from API */
typedef int MPI_Comm;
typedef int MPI_Datatype;
#define MPI_INT ((MPI_Datatype)0x4c000405)

typedef int MPI_Op;
#define MPI_SUM     (MPI_Op)(0x58000003)
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);

#if defined(HAVE_VISIBILITY)
#define MPICH_API_PUBLIC __attribute__((visibility ("default")))
#else
#define MPICH_API_PUBLIC
#endif
int MPI_Finalize(void) MPICH_API_PUBLIC;
int MPI_Comm_size(MPI_Comm comm, int *size) MPICH_API_PUBLIC;
int MPI_Comm_rank(MPI_Comm comm, int *rank) MPICH_API_PUBLIC;
int MPI_Init(int *argc, char ***argv) MPICH_API_PUBLIC;

/* libMyLib MPI struct & macros */
namespace libMyLib{
    extern int mpi_rank;
    extern int mpi_nranks;
    extern int mpi_msg;
    extern int mpi_msg_;
    extern MPI_Comm mpi_active_comm;
}

#define MPI_INIT MPI_Init(&argc, &argv); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_INIT_NULL MPI_Init(nullptr, nullptr); MPI_Comm_size( libMyLib::mpi_active_comm, &libMyLib::mpi_nranks ); MPI_Comm_rank( libMyLib::mpi_active_comm, &libMyLib::mpi_rank );
#define MPI_FINISH MPI_Finalize( );

#define MPI_INTERRUPT libMyLib::mpi_msg = 1; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);
#define MPI_ERROR_CHECK libMyLib::mpi_msg = 0; MPI_Allreduce(&libMyLib::mpi_msg, &libMyLib::mpi_msg_, 1, MPI_INT, MPI_SUM, libMyLib::mpi_active_comm);; if( libMyLib::mpi_msg_ > 0 ){throw std::runtime_error(" eror " );}

#endif //INC_MyLib_MPIWRAPPER_H

Проблема в том, что в одном коде мне нужно объединить эту обертку с настоящим заголовком mpi.h, и я получаю такие ошибки:

/usr/bin/ld: ../../lib/liblibMyLib.a(Reader.cpp.o): in function `libMyLib::Reader::read()':
Reader.cpp:(.text+0x10f3): undefined reference to `MPI_Allreduce(void const*, void*, int, int, int, int)'
/usr/bin/ld: Reader.cpp:(.text+0x1764): undefined reference to `MPI_Allreduce(void const*, void*, int, int, int, int)'
collect2: error: ld returned 1 exit status

Хотя я могу понять, что происходит, мне любопытно, если есть какой-нибудь способ, как сделать предварительное объявление, чтобы иметь возможность использовать упаковщик и объединить его с заголовком mpi.h, если необходимо?

1 Ответ

0 голосов
/ 22 октября 2019

Я не знаю, почему вы пытаетесь это сделать или она будет работать правильно вообще, но конкретная ошибка, которую вы наблюдаете сейчас, заключается в том, что MPI - это библиотека C.

C ++ относится к Cсущности отдельно от сущностей C ++. Поэтому, если вы объявляете функцию MPI_Allreduce в коде C ++, она не ссылается на ту же функцию MPI_Allreduce, которую вы получили бы, если бы использовали такое же объявление в коде C.

Чтобы создать имяесли обратиться к сущности C, вы должны объявить ее с помощью языка C, который делается с помощью

extern "C" {
    // declarations go here
}

. Вы можете заглянуть в mpi.h, чтобы увидеть, что он делает то же самое.

...