在 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,则可能需要分布式和共享数据的某种组合。
我有兴趣为我们的几个 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,则可能需要分布式和共享数据的某种组合。