Communicator(通讯)
<p><strong>Communicator</strong></p>
<p>通讯事件解析</p>
<p><strong>Communicator API 设置接口</strong>
<a href="https://github.com/qianyongjun895/HPIPS/tree/master/OpenMpi-Chain/ompi/communicator">https://github.com/qianyongjun895/HPIPS/tree/master/OpenMpi-Chain/ompi/communicator</a>
<strong>comm_request 通讯请求接口</strong></p>
<p><strong>ompi_comm_request_t 定义</strong>
typedef struct ompi_comm_request_t {</p>
<pre><code>ompi_request_t super;
opal_object_t *context;
opal_list_t schedule;</code></pre>
<p>} ompi_comm_request_t;</p>
<p>typedef int (<em>ompi_comm_request_callback_fn_t) (ompi_comm_request_t </em>);
<strong>通讯请求初始化函数</strong>
void ompi_comm_request_init (void);
<strong>通讯请求完成函数</strong>
void ompi_comm_request_fini (void);
<strong>通讯请求任务追加函数</strong>
int ompi_comm_request_schedule_append (ompi_comm_request_t *request, ompi_comm_request_callback_fn_t callback,</p>
<pre><code> ompi_request_t *subreqs[], int subreq_count);</code></pre>
<p><strong>通讯请求开始函数</strong>
void ompi_comm_request_start (ompi_comm_request_t <em>request);
<strong>获取通讯请求函数</strong>
ompi_comm_request_t </em>ompi_comm_request_get (void);
<strong>获取通讯请求返回函数</strong>
void ompi_comm_request_return (ompi_comm_request_t *request);</p>
<p><strong>communicator 通讯接口</strong>
<strong>宏定义声明</strong>
<strong>define OMPI_COMM_INTER 0x00000001</strong>
<strong>define OMPI_COMM_NAMEISSET 0x00000002</strong>
<strong>define OMPI_COMM_INTRINSIC 0x00000004</strong>
<strong>define OMPI_COMM_DYNAMIC 0x00000008</strong>
<strong>define OMPI_COMM_ISFREED 0x00000010</strong>
<strong>define OMPI_COMM_INVALID 0x00000020</strong>
<strong>define OMPI_COMM_CART 0x00000100</strong>
<strong>define OMPI_COMM_GRAPH 0x00000200</strong>
<strong>define OMPI_COMM_DIST_GRAPH 0x00000400</strong>
<strong>define OMPI_COMM_PML_ADDED 0x00001000</strong>
<strong>define OMPI_COMM_EXTRA_RETAIN 0x00004000</strong>
一些实用的宏定义
<strong>define OMPI_COMM_IS_INTER(comm) ((comm)->c_flags & OMPI_COMM_INTER)</strong>
<strong>define OMPI_COMM_IS_INTRA(comm) (!((comm)->c_flags & OMPI_COMM_INTER))</strong>
<strong>define OMPI_COMM_IS_CART(comm) ((comm)->c_flags & OMPI_COMM_CART)</strong>
<strong>define OMPI_COMM_IS_GRAPH(comm) ((comm)->c_flags & OMPI_COMM_GRAPH)</strong>
<strong>define OMPI_COMM_IS_DIST_GRAPH(comm) ((comm)->c_flags & OMPI_COMM_DIST_GRAPH)</strong>
<strong>define OMPI_COMM_IS_INTRINSIC(comm) ((comm)->c_flags & OMPI_COMM_INTRINSIC)</strong>
<strong>define OMPI_COMM_IS_FREED(comm) ((comm)->c_flags & OMPI_COMM_ISFREED)</strong>
<strong>define OMPI_COMM_IS_DYNAMIC(comm) ((comm)->c_flags & OMPI_COMM_DYNAMIC)</strong>
<strong>define OMPI_COMM_IS_INVALID(comm) ((comm)->c_flags & OMPI_COMM_INVALID)</strong>
<strong>define OMPI_COMM_IS_PML_ADDED(comm) ((comm)->c_flags & OMPI_COMM_PML_ADDED)</strong>
<strong>define OMPI_COMM_IS_EXTRA_RETAIN(comm) ((comm)->c_flags & OMPI_COMM_EXTRA_RETAIN)</strong>
<strong>define OMPI_COMM_IS_TOPO(comm) (OMPI_COMM_IS_CART((comm)) || OMPI_COMM_IS_GRAPH((comm)) || OMPI_COMM_IS_DIST_GRAPH((comm)))</strong>
<strong>define OMPI_COMM_SET_DYNAMIC(comm) ((comm)->c_flags |= OMPI_COMM_DYNAMIC)</strong>
<strong>define OMPI_COMM_SET_INVALID(comm) ((comm)->c_flags |= OMPI_COMM_INVALID)</strong>
<strong>define OMPI_COMM_SET_PML_ADDED(comm) ((comm)->c_flags |= OMPI_COMM_PML_ADDED)</strong>
<strong>define OMPI_COMM_SET_EXTRA_RETAIN(comm) ((comm)->c_flags |= OMPI_COMM_EXTRA_RETAIN)</strong>
一组特殊标签
在 comm_connect_accept 例程中识别 MPI_Comm_join
<strong>define OMPI_COMM_ALLGATHER_TAG -31078</strong>
<strong>define OMPI_COMM_BARRIER_TAG -31079</strong>
<strong>define OMPI_COMM_ALLREDUCE_TAG -31080</strong>
获取新的通信 id. 所需的模式第一个 (内部) 表示输入通信是否是内部通信, 第二个是新的通信器是否是内部通信
<strong>define OMPI_COMM_CID_INTRA 0x00000020</strong>
<strong>define OMPI_COMM_CID_INTER 0x00000040</strong>
<strong>define OMPI_COMM_CID_INTRA_BRIDGE 0x00000080</strong>
<strong>define OMPI_COMM_CID_INTRA_PMIX 0x00000100</strong>
<strong>define OMPI_COMM_CID_GROUP 0x00000200</strong>
<strong>define cid 分配给 MPI_COMM_WORLD 和其他通信者的块</strong>
<strong>define OMPI_COMM_BLOCK_WORLD 16</strong>
<strong>define OMPI_COMM_BLOCK_OTHERS 8</strong>
比较两个 cid 的宏
<strong>define OMPI_COMM_CID_IS_LOWER(comm1,comm2) ( ((comm1)->c_contextid < (comm2)->c_contextid)? 1:0)</strong>
<strong>ompi_communicator_t 定义</strong>
struct ompi_communicator_t {</p>
<pre><code>opal_object_t c_base;
opal_mutex_t c_lock; 名称和潜在属性的互斥体
char c_name[MPI_MAX_OBJECT_NAME];
uint32_t c_contextid;
int c_my_rank;
uint32_t c_flags; 标记, e.g. intercomm,拓扑, 等.
int c_id_available; 当前可用于分配给子级的 Cid
int c_id_start_index; 分配给此通信器的 cid 块的起始索引
ompi_group_t *c_local_group;
ompi_group_t *c_remote_group;
struct ompi_communicator_t *c_local_comm; 本地通信器的副本, 以防通信是通信的
/* 属性 */
struct opal_hash_table_t *c_keyhash;
/*CUDA 尺寸*/
int c_cube_dim;
/* 有关所选拓扑模块的标准信息 (如果不是购物车、图形或区图形通信器, 则为 NULL) */
struct mca_topo_base_module_t* c_topo;
/* 在 Fortran 中的索引 &lt;-&gt; C 转换数组 */
int c_f_to_c_index;
/* PERUSE事件的位置持有者.*/
struct ompi_peruse_handle_t** c_peruse_handles;
/* 错误处理。 此字段不具有 &quot;c_ &quot; 前缀, 因此 OMPI_ERRHDL_ * 宏可以找到它, 而不管它是通信、窗口还是文件。 */
ompi_errhandler_t *error_handler;
ompi_errhandler_type_t errhandler_type;
/* 挂钩的 PML 挂东西 */
struct mca_pml_comm_t *c_pml_comm;
/* 集体模块接口和数据*/
mca_coll_base_comm_coll_t *c_coll;</code></pre>
<p>};</p>
<p>typedef struct ompi_communicator_t ompi_communicator_t;
<strong>判断通讯是不是有效</strong>
static inline int ompi_comm_invalid(ompi_communicator_t<em> comm)
<strong>获取通讯的等级函数</strong>
static inline int ompi_comm_rank(ompi_communicator_t</em> comm)
<strong>获取通讯的尺寸</strong>
static inline int ompi_comm_size(ompi_communicator_t<em> comm)
<strong>远程组的大小, 用于相互通信。为内部通信器返回零</strong>
static inline int ompi_comm_remote_size(ompi_communicator_t</em> comm)
<strong>通信器的上下文 ID, 适合传递给 ompi_comm_lookup 以获取通信</strong>
static inline uint32_t ompi_comm_get_cid(ompi_communicator_t<em> comm)
<strong>返回指向与上下文 id cid 关联的通信器的指针, 没有进行错误检查</strong>
static inline ompi_communicator_t </em>ompi_comm_lookup(uint32_t cid)
<strong>ID指针查找</strong>
static inline struct ompi_proc_t<em> ompi_comm_peer_lookup(ompi_communicator_t</em> comm, int peer_id)
<strong>无效查找</strong>
static inline bool ompi_comm_peer_invalid(ompi_communicator_t<em> comm, int peer_id)
<strong>初始 MPI_COMM_WORLD 和 MPI_COMM_SELF</strong>
int ompi_comm_init(void);
<strong>从通信器中提取本地组</strong>
OMPI_DECLSPEC int ompi_comm_group (ompi_communicator_t </em>comm, ompi_group_t <strong>group);
</strong>基于组创建通信器<strong>
int ompi_comm_create (ompi_communicator_t<em> comm, ompi_group_t </em>group, ompi_communicator_t</strong> newcomm);
<strong>基于组的非集体创建通信器</strong>
int ompi_comm_create_group (ompi_communicator_t <em>comm, ompi_group_t </em>group, int tag,ompi_communicator_t **newcomm);</p>
<p><strong>采取一个几乎完全的通信器, 并保留 CID 以及激活它 (初始化的集体和拓扑)。</strong>
int ompi_comm_enable(ompi_communicator_t *old_comm,</p>
<pre><code> ompi_communicator_t *new_comm,
int new_rank,
int num_procs,
ompi_proc_t** topo_procs);</code></pre>
<p><strong>MPI_DIST_GRAPH_CREATE_ADJACENT 后端</strong></p>
<p>int ompi_topo_dist_graph_create_adjacent(ompi_communicator_t *old_comm,</p>
<pre><code> int indegree, int sources[],
int sourceweights[], int outdegree,
int destinations[], int destweights[],
MPI_Info info, int reorder,
MPI_Comm *comm_dist_graph);</code></pre>
<p><strong>根据颜色和密钥拆分通信器。参数与该函数的 MPI 对应项相同。</strong>
OMPI_DECLSPEC int ompi_comm_split (ompi_communicator_t *comm, int color, int key, ompi_communicator_t** newcomm, bool pass_on_topo);</p>
<p><strong>根据类型和密钥拆分通信器。参数与函数的 MPI-对应项相同</strong></p>
<p>OMPI_DECLSPEC int ompi_comm_split_type(ompi_communicator_t <em>comm, int split_type, int key,struct ompi_info_t </em>info, ompi_communicator_t<strong> newcomm);
</strong>一个沟通者。参数与该函数的 MPI 对应项相同。它已经被提取出来了, 因为我们也需要能够在内部传播一个通信器。**</p>
<p>OMPI_DECLSPEC int ompi_comm_dup (ompi_communicator_t *comm, ompi_communicator_t **newcomm);</p>
<p><strong>一个通信器 (非阻塞)。参数与该函数的 MPI 对应项相同。它已经被提取出来了, 因为我们也需要能够在内部传播一个通信器。</strong></p>
<p>OMPI_DECLSPEC int ompi_comm_idup (ompi_communicator_t *comm, ompi_communicator_t <strong>newcomm, ompi_request_t </strong>request);
<strong>与信息沟通。参数与该函数的 MPI 对应项相同。它已经被提取出来了, 因为我们也需要能够在内部传播一个通信器。</strong></p>
<p>OMPI_DECLSPEC int ompi_comm_dup_with_info (ompi_communicator_t <em>comm, ompi_info_t </em>info, ompi_communicator_t **newcomm);</p>
<p><strong>使用函数的信息进行通信 (非阻塞)。它已经被提取出来了, 因为我们也需要能够在内部传播一个通信器。</strong></p>
<p>OMPI_DECLSPEC int ompi_comm_idup_with_info (ompi_communicator_t <em>comm, ompi_info_t </em>info, ompi_communicator_t <strong>newcomm, ompi_request_t </strong>req);</p>
<p><strong>比较两个通讯。</strong></p>
<p>int ompi_comm_compare(ompi_communicator_t <em>comm1, ompi_communicator_t </em>comm2, int *result);</p>
<p><strong>释放一个通讯</strong>
OMPI_DECLSPEC int ompi_comm_free (ompi_communicator_t **comm);</p>
<p><strong>分配新的通信器结构</strong>
ompi_communicator_t* ompi_comm_allocate (int local_group_size, int remote_group_size);</p>
<p><strong>分配新的通信器 ID</strong>
OMPI_DECLSPEC int ompi_comm_nextcid (ompi_communicator_t <em>newcomm, ompi_communicator_t </em>comm, ompi_communicator_t <em>bridgecomm, const void </em>arg0, const void *arg1,bool send_first, int mode);</p>
<p><strong>分配新的通信器 ID (非阻塞)</strong>
OMPI_DECLSPEC int ompi_comm_nextcid_nb (ompi_communicator_t <em>newcomm, ompi_communicator_t </em>comm,ompi_communicator_t <em>bridgecomm, const void </em>arg0, const void *arg1,bool send_first, int mode, ompi_request_t **req);</p>
<p><strong>关闭通信器基础结构</strong>
int ompi_comm_finalize (void);</p>
<p><strong>这是例行程序, 所有的通信器设置</strong>
OMPI_DECLSPEC int ompi_comm_set ( ompi_communicator_t*<em> newcomm,ompi_communicator_t</em> oldcomm,int local_size,int <em>local_ranks,int remote_size,int </em>remote_ranks,opal_hash_table_t <em>attr,ompi_errhandler_t </em>errh,bool copy_topocomponent,
ompi_group_t <em>local_group,ompi_group_t </em>remote_group );</p>
<p><strong>这是例行程序, 所有的通信器的东西是真正设置。非阻塞版本</strong></p>
<p>OMPI_DECLSPEC int ompi_comm_set_nb ( ompi_communicator_t *<em>ncomm, ompi_communicator_t </em>oldcomm,int local_size,int <em>local_ranks,int remote_size,int </em>remote_ranks,opal_hash_table_t <em>attr,ompi_errhandler_t </em>errh,bool copy_topocomponent,
ompi_group_t <em>local_group,ompi_group_t </em>remote_group,
ompi_request_t **req );</p>
<p><strong>这是一个在 intercomm_create 中使用的短手式惯例。例程确保, 所有进程事后都有一个远程组的 ompi_proc_t 指针列表</strong>
struct ompi_proc_t *<em>ompi_comm_get_rprocs ( ompi_communicator_t </em>local_comm, ompi_communicator_t *bridge_comm,int local_leader, int remote_leader,int tag,int rsize);</p>
<p><strong>这个例程验证, local_group 和远程组是否在 intercomm_create 中重叠</strong></p>
<p>int ompi_comm_overlapping_groups (int size, struct ompi_proc_t <strong> lprocs,int rsize, struct ompi_proc_t </strong> rprocs);</p>
<p><strong>这是一个例行决定本地或远程组是否将首先在新的内部 comm。只是在 MPI_Intercomm_merge 内使用</strong></p>
<p>int ompi_comm_determine_first ( ompi_communicator_t *intercomm, int high );</p>
<p>OMPI_DECLSPEC int ompi_comm_activate (ompi_communicator_t *<em>newcomm, ompi_communicator_t </em>comm, ompi_communicator_t <em>bridgecomm, const void </em>arg0,const void *arg1, bool send_first, int mode);</p>
<p><strong>comm_activate 的非阻塞变体</strong>
OMPI_DECLSPEC int ompi_comm_activate_nb (ompi_communicator_t <strong>newcomm, ompi_communicator_t <em>comm, ompi_communicator_t </em>bridgecomm, const void <em>arg0,const void </em>arg1, bool send_first, int mode, ompi_request_t </strong>req);</p>
<p><strong>用于转储结构的简单函数</strong>
int ompi_comm_dump ( ompi_communicator_t *comm );</p>
<p><strong>设置名称</strong>
int ompi_comm_set_name (ompi_communicator_t <em>comm, const char </em>name );</p>
<p><strong>全局变量保存数字 od 动态通信</strong>
extern int ompi_comm_num_dyncomm;</p>
<p><strong>检查是否有任何进程请求支持
MPI_THREAD_MULTIPLE注意, 这会在 MPI_COMM_WORLD 中生成全局信息, 与本地标志 ompi_mpi_thread_provided</strong></p>
<p>OMPI_DECLSPEC int ompi_comm_cid_init ( void );</p>