Я использую короткую оболочку 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, если необходимо?

0
Eenoku 22 Окт 2019 в 01:51

1 ответ

Лучший ответ

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

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

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

extern "C" {
    // declarations go here
}

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

0
walnut 21 Окт 2019 в 23:36