在 OpenMDAO 中使用具有底层并行性的代码

Using code with underlying parallelism in OpenMDAO

我有兴趣为我们的几个 OpenMDAO 组件添加底层并行性。这些组件中的大部分代码是用 Fortran 语言编写的。 Fortran 代码包装在 python 中,然后在 OpenMDAO 中用作 python 模块。我想 运行 使用 OpenMP 或 OpenMPI 并行处理这些 Fortran 代码。我们已经计划使用 OpenMDAO 的内置并行功能,因此这将是第二层并行性。这可行吗?如果是这样,您是否有适合 OpenMDAO 的推荐方法?

首先我将解决有关 OpenMP 的问题。目前 OpenMDAO 本身不使用 OpenMP,我们也没有任何计划在短期内改变它。所以这意味着,我们框架根本不知道或不关心您是否碰巧在您的 Fortran 代码中使用它。随意,关于 MPI + OpenMP 代码的所有正常警告当然有效!

如果您想在组件本身中使用 MPI 并行性,那是 OpenMDAO 直接支持的。对于这种情况,我们有一个 fairly simple tutorial,组件本身想要请求多个处理器。本教程的显着特点是组件向框架请求多个处理器:

def get_req_procs(self):
    """
    min/max number of cpus that this component can use
    """
    return (1,self.size)

在这种情况下,组件将接受从 1 个 proc 到其数组中的元素数的任何位置。在您的情况下,您可能希望将其限制为单个值,在这种情况下,您可以 return 单个整数。

另一个值得注意的部分是:

def setup_distrib_idxs(self):
    """
    specify the local sizes of the variables and which specific indices this specific
    distributed component will handle. Indices do NOT need to be sequential or
    contiguous!
    """

    comm = self.comm
    rank = comm.rank

    #NOTE: evenly_distrib_idxs is a helper function to split the array up as evenly as possible
    sizes, offsets = evenly_distrib_idxs(comm.size, self.size)
    local_size, local_offset = sizes[rank], offsets[rank]
    self.local_size = int(local_size)

    start = local_offset
    end = local_offset + local_size

    self.set_var_indices('x', val=np.zeros(local_size, float),
        src_indices=np.arange(start, end, dtype=int))
    self.set_var_indices('y', val=np.zeros(local_size, float),
        src_indices=np.arange(start, end, dtype=int))

此代码告诉框架您的分布式数据如何在多个过程中拆分。这种方法的细节在不同的实现中会有很大的不同。在某些情况下,您可能让所有过程都拥有所有数据。在其他情况下(比如这个),您将在过程中均匀分布数据。在其他情况下,您可能拥有全局数据和分布式数据的组合。

如果您打算只使用 OpenMP,您可能会在所有进程之间共享所有数据,但仍然请求超过 1 个进程。这样你就可以确保 OpenMDAO 为你的 comp 分配了足够的 proc,使其在多线程上下文中很有用。您将获得一个 comm 对象,您可以使用它来分配任务。

如果您打算使用纯 MPI,则很可能(但不确定)您将使用分布式数据。您仍然希望请求超过 1 个过程,但您还必须拆分数据。

如果您决定使用 OpenMP 和 MPI,则可能需要分布式和共享数据的某种组合。