如何编写用于动态加载的MPI包装器

blu*_*ion 5 c c++ loading dynamic mpi

由于MPI不提供二进制兼容性,仅提供源兼容性,因此我们被迫将求解器源代码交付给客户,以使他们将求解器与首选版本的MPI一起使用。好了,我们到达了无法再提供源代码的地步。

因此,我正在研究围绕MPI调用创建包装器的方法。我们的想法是为我们提供存根函数的标头,用户将编写实现,从中创建一个动态库,然后我们的求解器将在运行时加载它。

但是解决方案不是“优雅”的,而且容易出错。由于有些实struct参(例如MPI_Request)的struct定义可能因一个MPI实现而异,因此我们需要接受(void*)许多存根实参。另外,如果一个MPI到另一个MPI的参数数量可以不同(我不确定是否可以保证不会发生),那么使用唯一的方法就是使用var_args

//header (provided by us)
int my_stub_mpi_send(const void buf, int count, void* datatype,
        int dest, int tag, void* comm);

//*.c (provided by user)
#include <my_stub_mpi.h>
#include <mpi.h>
int my_stub_mpi_send(const void buf, int count, void* datatype,
        int dest, int tag, void* comm)
{
    return MPI_Send(buf, count, *((MPI_Datatype) datatype),
            dest, tag, ((MPI_Comm) comm));
}
//Notes: (1) Most likely the interface will be C, not C++,
//           unless I can make a convincing case for C++;
//       (2) The goal here is to avoid *void pointers, if possible;
Run Code Online (Sandbox Code Playgroud)

我的问题是,是否有人知道解决这些问题的方法?

jxh*_*jxh 1

这似乎是桥接模式的一个明显用例。

在这种情况下,MPI 的通用接口是Implementor。客户需要为其特定的 MPI 实例提供ConcreteImplementor 。您的求解器代码将是RefinedAbstraction,因为Abstraction提供了通往Implementor 的桥梁。

Abstract_Solver <>--> MPI_Interface
      .                    .
     /_\                  /_\
      |                    |

    Solver            MPI_Instance
Run Code Online (Sandbox Code Playgroud)

客户继承MPI_Interface并根据其选择的 MPI 实例实现它。然后,该实现被馈送到求解器接口并在Abstract_Solver其工作时被使用。

因此,您可以MPI_Interface根据需要确保类型安全,以Abstract_Solver完成其工作。没有void *必要。的实现者MPI_Instance可以将其所需的任何特定于实现的 MPI 状态存储在其实例化对象中,该实例化对象将需要满足接口所需的契约。例如,comm可以从 中删除该参数MPI_Interface。该接口可以假设一个单独的实例comm需要一个单独的实例MPI_Instance(初始化为不同的实例comm)。

虽然桥接模式是面向对象的,但该解决方案并不限于 C++。您可以轻松地在 C 中指定一个抽象接口(如这个动态调度示例所示)。