18、MPI命令总结与Fortran和C语言通信详解

MPI命令总结与Fortran和C语言通信详解

1. MPI命令概述

MPI(Message Passing Interface)是一种用于并行计算的标准,提供了一系列用于进程间通信的命令。下面将详细介绍MPI的各种命令及其功能。

1.1 点对点通信

1.1.1 MPI_Sendrecv_replace

该函数将缓冲区的内容发送到目标进程,并从源进程接收数据替换缓冲区的内容。其函数原型如下:

int MPI_Sendrecv_replace(
    void *message,  /* input/output */
    int count,      /* input */
    MPI_Datatype datatype, /* input */
    int dest,       /* input */
    int sendtag,    /* input */
    int source,     /* input */
    int recvtag,    /* input */
    MPI_Comm comm,  /* input */
    MPI_Status *status /* output */
)

1.2 集体通信

1.2.1 广播和屏障
  • MPI_Barrier :阻塞 comm 中的所有进程,直到每个进程都调用了该函数。函数原型为:
int MPI_Barrier(
    MPI_Comm comm /* input */
)
  • MPI_Bcast :将根进程( root )的 send_data 内容广播到 comm 中的所有进程,包括根进程本身。函数原型为:
int MPI_Bcast(
    void *send_data, /* input/output */
    int count,       /* input */
    MPI_Datatype datatype, /* input */
    int root,        /* input */
    MPI_Comm comm    /* input */
)
1.2.2 散射和收集操作
  • MPI_Gather :将 comm 中每个进程的 send_data 收集到根进程的 recv_data 中。函数原型为:
int MPI_Gather(
    void *send_data, /* input */
    int sendcount,   /* input */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int recvcount,   /* input */
    MPI_Datatype recvtype, /* input */
    int root,        /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Gatherv :与 MPI_Gather 类似,但允许不同进程的数据具有不同的类型签名。函数原型为:
int MPI_Gatherv(
    void *send_data, /* input */
    int sendcount,   /* input */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int *recvcounts, /* input array */
    int *recvoffsets, /* input array */
    MPI_Datatype recvtype, /* input */
    int root,        /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Scatter :将根进程的 send_data 散射到 comm 中的每个进程。函数原型为:
int MPI_Scatter(
    void *send_data, /* input */
    int sendcount,   /* input */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int recvcount,   /* input */
    MPI_Datatype recvtype, /* input */
    int root,        /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Scatterv :与 MPI_Scatter 类似,但允许不同进程的数据具有不同的类型签名。函数原型为:
int MPI_Scatterv(
    void *send_data, /* input */
    int *sendcounts, /* input array */
    int *sendoffsets, /* input array */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int recvcount,   /* input */
    MPI_Datatype recvtype, /* input */
    int root,        /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Allgather :收集 comm 中所有进程的 send_data 到每个进程的 recv_data 中。函数原型为:
int MPI_Allgather(
    void *send_data, /* input */
    int sendcount,   /* input */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int recvcount,   /* input */
    MPI_Datatype recvtype, /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Allgatherv :与 MPI_Allgather 类似,但允许不同进程的数据具有不同的类型签名。函数原型为:
int MPI_Allgatherv(
    void *send_data, /* input */
    int sendcount,   /* input */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int *recvcounts, /* input array */
    int *offsets,    /* input array */
    MPI_Datatype recvtype, /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Alltoall :所有进程之间进行全对全的散射和收集操作,每个进程共享其他进程的 send_data 。函数原型为:
int MPI_Alltoall(
    void *send_data, /* input */
    int sendcount,   /* input */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int recvcount,   /* input */
    MPI_Datatype recvtype, /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Alltoallv :与 MPI_Alltoall 类似,但允许不同进程的数据具有不同的类型签名。函数原型为:
int MPI_Alltoallv(
    void *send_data, /* input */
    int *sendcounts, /* input array */
    int *sendoffsets, /* input array */
    MPI_Datatype sendtype, /* input */
    void *recv_data, /* output */
    int *recvcounts, /* input array */
    int *recvoffsets, /* input array */
    MPI_Datatype recvtype, /* input */
    MPI_Comm comm    /* input */
)
1.2.3 归约操作
  • MPI_Reduce :对 comm 中每个进程的 segment 数据进行归约操作,结果存储在根进程的 result 中。函数原型为:
int MPI_Reduce(
    void *segment,   /* input */
    void *result,    /* output */
    int count,       /* input */
    MPI_Datatype datatype, /* input */
    MPI_Op operator, /* input */
    int root,        /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Allreduce :对 comm 中每个进程的 segment 数据进行归约操作,结果存储在每个进程的 result 中。函数原型为:
int MPI_Allreduce(
    void *segment,   /* input */
    void *result,    /* output */
    int count,       /* input */
    MPI_Datatype datatype, /* input */
    MPI_Op operator, /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Op_create :创建一个用于 MPI_Allreduce 的操作。 fen 是一个指向返回 void 的函数的指针, commute 表示操作数是否可交换。函数原型为:
int MPI_Op_create(
    MPI_User_function *fen, /* input */
    int commute,            /* input */
    MPI_Op *operator        /* output */
)
  • MPI_Op_free :释放由 MPI_Op_create 定义的操作。函数原型为:
int MPI_Op_free(
    MPI_Op *operator /* input/output */
)
  • MPI_Reduce_scatter :对 comm 中每个进程的 segment 数据进行归约操作,并将结果散射到每个进程的 recv_data 中。函数原型为:
int MPI_Reduce_scatter(
    void *segment,   /* input */
    void *recv_data, /* output */
    int *recvcounts, /* input */
    MPI_Datatype datatype, /* input */
    MPI_Op operator, /* input */
    MPI_Comm comm    /* input */
)
  • MPI_Scan :对 comm 中每个进程的 segment 数据进行部分归约操作,结果存储在每个进程的 result 中。函数原型为:
int MPI_Scan(
    void *segment,   /* input */
    void *result,    /* output */
    int count,       /* input */
    MPI_Datatype datatype, /* input */
    MPI_Op operator, /* input */
    MPI_Comm comm    /* input */
)

1.3 预定义的归约操作

MPI提供了一系列预定义的归约操作,如下表所示:
| MPI操作 | 操作描述 |
| ---- | ---- |
| MPLMAX | 最大值 |
| MPLMIN | 最小值 |
| MPLSUM | 求和 |
| MPLPROD | 乘积 |
| MPLBAND | 布尔与 |
| MPLLAND | 逻辑与 |
| MPLBOR | 布尔或 |
| MPLLOR | 逻辑或 |
| MPLBXOR | 布尔异或 |
| MPLLXOR | 逻辑异或 |
| MPLMAXLOC | 最大值及其位置 |
| MPLMINLOC | 最小值及其位置 |

1.4 支持归约操作的MPI数据类型

MPI还提供了一系列用于归约操作的数据类型,如下表所示:
| MPI数据类型 | 等效的C数据类型 |
| ---- | ---- |
| MPLCHAR | 有符号字符 |
| MPLSHORT | 有符号短整型 |
| MPLINT | 有符号整型 |
| MPLLONG | 有符号长整型 |
| MPLFLOAT | 单精度浮点数 |
| MPLDOUBLE | 双精度浮点数 |
| MPLLONG_DOUBLE | 长双精度浮点数 |

1.5 通信器和通信器组

1.5.1 访问通信器组
  • MPI_Comm_group :获取给定通信器关联的组。如果 comm 是一个跨通信器,则返回本地组。函数原型为:
int MPI_Comm_group(
    MPI_Comm comm,  /* input */
    MPI_Group *group /* output */
)
1.5.2 组比较和操作
  • MPI_Group_compare :比较两个组 groupl group2 ,结果可能为相同、相似或不相等。函数原型为:
int MPI_Group_compare(
    MPI_Group groupl, /* input */
    MPI_Group group2, /* input */
    int *result       /* output */
)
  • MPI_Group_difference :比较两个组 groupl group2 ,形成一个新组,该组包含 groupl 中不在 group2 中的元素。函数原型为:
int MPI_Group_difference(
    MPI_Group groupl, /* input */
    MPI_Group group2, /* input */
    MPI_Group *group3 /* output */
)
  • MPI_Group_excl :从 group 中排除指定排名( ranks )的元素,形成一个新组 group_out 。函数原型为:
int MPI_Group_excl(
    MPI_Group group, /* input */
    int nr,          /* input */
    int *ranks,      /* input array */
    MPI_Group *group_out /* output */
)
  • MPI_Group_free :释放一个组。函数原型为:
int MPI_Group_free(
    MPI_Group group /* input */
)
  • MPI_Group_incl :根据指定排名( ranks )从 group 中选择元素,形成一个新组 group_out 。函数原型为:
int MPI_Group_incl(
    MPI_Group group, /* input */
    int nr,          /* input */
    int *ranks,      /* input */
    MPI_Group *group_out /* output */
)
  • MPI_Group_intersection :求两个组 groupl group2 的交集,形成一个新组 group_out 。函数原型为:
int MPI_Group_intersection(
    MPI_Group groupl, /* input */
    MPI_Group group2, /* input */
    MPI_Group *group_out /* output */
)
  • MPI_Group_rank :返回调用进程在组中的排名。函数原型为:
int MPI_Group_rank(
    MPI_Group group, /* input */
    int *rank        /* output */
)
  • MPI_Group_size :返回组中元素(进程)的数量。函数原型为:
int MPI_Group_size(
    MPI_Group group, /* input */
    int *size        /* output */
)
  • MPI_Group_union :求两个组 groupl group2 的并集,形成一个新组 group_out 。函数原型为:
int MPI_Group_union(
    MPI_Group groupl, /* input */
    MPI_Group group2, /* input */
    MPI_Group *group_out /* output */
)
1.5.3 管理通信器
  • MPI_Comm_compare :比较两个通信器 comml comm2 ,结果可能为相同、全等、相似或不相等。函数原型为:
int MPI_Comm_compare(
    MPI_Comm comml,  /* input */
    MPI_Comm comm2,  /* input */
    int *result      /* output */
)
  • MPI_Comm_create :从输入的 comm group 创建一个新的通信器 comm_out 。函数原型为:
int MPI_Comm_create(
    MPI_Comm comm,   /* input */
    MPI_Group group, /* input */
    MPI_Comm *comm_out /* output */
)
  • MPI_Comm_free :释放一个通信器。函数原型为:
int MPI_Comm_free(
    MPI_Comm *comm /* input/output */
)

1.6 通信状态结构

MPI定义了一个通信状态结构 MPI_Status ,用于存储通信操作的状态信息。其定义如下:

typedef struct {
    int count;
    int MPI_SOURCE;
    int MPI_TAG;
    int MPI_ERROR;
    int private_count;
} MPI_Status;

1.7 定时器、初始化和杂项

1.7.1 定时器
  • MPI_Wtick :返回 MPI_Wtime 的分辨率(精度),单位为秒。函数原型为:
double MPI_Wtick(void)
  • MPI_Wtime :返回自上次本地调用该函数以来的挂钟时间,单位为秒。这是一个本地定时器,其他进程的调用不会影响本地计时。函数原型为:
double MPI_Wtime(void)
1.7.2 启动和结束
  • MPI_Abort :终止 comm 中的所有进程,并向调用进程返回一个错误代码。函数原型为:
int MPI_Abort(
    MPI_Comm *comm, /* input */
    int error_code  /* input */
)
  • MPI_Finalize :终止当前的MPI线程,并清理MPI分配的内存。函数原型为:
int MPI_Finalize(void)
  • MPI_Init :启动MPI。在使用任何其他MPI函数之前,必须调用该函数。函数原型为:
int MPI_Init(
    int *argc,      /* input/output */
    char **arv      /* input/output */
)
1.7.3 用户定义函数原型

MPI_User_function 定义了一个用于 MPI_Op_create 的操作的基本模板。其定义如下:

typedef MPI_User_function(
    void *invec,     /* input vector */
    void *inoutvec,  /* input/output vector */
    int length,      /* length of vecs. */
    MPI_Datatype datatype /* type of vec elements */
)

2. Fortran和C语言通信

2.1 Fortran和C语言的主要区别

Fortran和C语言在参数传递、数组存储、动态数组、复数类型和指针支持等方面存在一些重要区别。

2.1.1 参数传递
  • Fortran通过地址(引用)将所有参数传递给过程(子例程和函数)。例如:
program address
    real x
    call subr(x)
    print *," x=",x
    stop
end

subroutine subr(y)
    real y
    y = 3.14159
    return
end
  • C语言通过值传递信息给过程,除了数组是通过地址传递。例如:
#include <stdio.h>

main()
{
    float x,*z;
    float y[1];
    void subrNOK(float),subrOK(float*,float*);
    subrNOK(x);  /* x will not be set */
    printf(" x=%e\n",x);
    subrOK(y,z);  /* y[0],z[0] are set */
    printf(" y[0] = %e, z = %e\n",y[0],*z);
}

void subrNOK(x)
    float x;
{
    x = 3.14159;
}

void subrOK(float *x,float *y)
{
    *x = 3.14159;
    y[0] = 2.71828;
}
2.1.2 数组存储
  • Fortran数组在第一个索引上是连续存储的,例如 a(2,j) 紧跟在 a(1,j) 之后。
  • C语言数组的第二个索引是“快速”索引,例如 a[i][2] 存储在 a[i][1] 之后。此外,C语言的索引通常从0开始,而Fortran从1开始。
2.1.3 动态数组
  • Fortran允许动态维度的数组。例如:
program dims
    real x(9)
    call subr(x)
    print *,x
    stop
end

subroutine subr(x)
    real x(3,3)
    do i=1,3
        do j=1,3
            x(j,i) = float(i+j)
        enddo
    enddo
    return
end
  • C语言不允许自动的动态维度数组,但可以通过宏定义来解决这个问题。例如:
#define am(i,j) *(a+i+lda*j)

void proc(int Ida, float *a)
{
    float seed=331.0, ggl(float*);
    int i,j;
    for(j=0;j<lda;j++){
        for(i=0;i<lda;i++){
            am(i,j) = ggl(&seed); /* Fortran order */
        }
    }
    #undef am
}
2.1.4 复数类型
  • Fortran支持复数类型,例如 complex z 实际上是一个二维数组 (Re(z), Im(z))
  • C语言在大多数情况下不支持复数类型,虽然Cray C和一些版本的Apple开发者工具包 gcc 支持复数类型,但没有统一的标准。在处理Fortran的复数数组时,通常将其映射到C语言的二维浮点数数组中。例如,如果Fortran中声明了 complex z(m) ,在C语言中可以使用 float z[m][2] 来访问,其中 Re(z[k]) = z[k-1][0] Im(z[k]) = z[k-1][1]
2.1.5 指针支持
  • C语言有广泛的指针支持,通过 &x 可以获取变量 x 的地址,通过 *px = y 可以修改指针 px 指向的变量的值。
  • Fortran中类似Cray的指针现在比较常见,但 g77 等编译器不支持Fortran指针。Fortran 90支持一种复杂的指针构造,但在许多Linux机器上不可用。

2.2 C语言调用Fortran例程

从C语言调用Fortran例程时,通常需要在Fortran例程名后面加下划线(Cray平台除外)。以下是一个示例,展示了如何传递标量和数组参数:

#include <stdio.h>

int main()
{
    int n=2;
    unsigned char cl='C',c2;
    float x[2];
    /* NOTE underscore */
    void subr_(int*,char*,char*,float*);
    subr_(&n,&cl,&c2,x);
    printf("n=%d, cl=%c, c2=%c,x=%e, %e\n",
           n,cl,c2,x[0],x[1]);
    return 0;
}

对应的Fortran例程如下:

subroutine subr(n,cl,c2,x)
    integer n
    character*1 cl,c2
    real x(n)
    print *,"in subr: cl=",cl
    c2='F'
    do i=1,n
        x(i) = float(i)
    enddo
    return
end

在C语言调用Fortran过程时,可能需要一些库,如 libf2c.a (或 libf2c.so )、 libftn.a (或 libftn.so )等。在Linux平台上,可能需要 libg2c.a 。可以使用 ar t libf2c.a 列出 libf2c.a 中的所有编译模块,使用 run libftn.so 列出 .so 对象中的所有命名模块。由于这些命令可能会产生大量输出,建议使用 grep 进行过滤。

2.3 Fortran调用C例程

从Fortran调用C例程时,同样需要注意命名约定。以下是一个示例:

program foo
    integer n
    real x(2)
    character*1 cl,c2
    cl = 'F'
    n = 2
    call subr(cl,c2,n,x)
    print *,"cl=",cl,", c2=",c2,", n=",n,
            ", x=",x(1),x(2)
end

对应的C例程如下:

#include <stdio.h>

void subr_(char *cl,char *c2,int *n,float *x)
{
    int i;
    printf("in subr: cl=%c\n",*cl);
    *c2 = 'C';
    for(i=0;i<*n;i++) x[i] = (float)i;
}

如果Fortran调用C过程,可能需要 libc.a libm.a 或它们的 .so 共享对象变体。同样,可以使用 ar run 命令来确定未满足的外部符号是否在这些库中。在这种情况下,通常最好使用Fortran编译器/链接器将C模块链接到Fortran程序中,例如:

g77 -o try foo.o subr.o

综上所述,MPI提供了丰富的命令集用于并行计算中的进程间通信,而Fortran和C语言在参数传递、数组存储等方面存在差异,在进行跨语言通信时需要注意这些差异并遵循相应的规则。通过合理使用MPI命令和处理Fortran和C语言的通信问题,可以实现高效的并行计算程序。

3. 流程图展示MPI操作流程

3.1 MPI集体通信流程

下面是一个mermaid格式的流程图,展示了MPI集体通信中广播和收集操作的基本流程:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B(初始化MPI):::process
    B --> C{选择操作类型}:::decision
    C -->|广播| D(根进程调用MPI_Bcast):::process
    D --> E(所有进程接收广播数据):::process
    C -->|收集| F(所有进程发送数据):::process
    F --> G(根进程调用MPI_Gather):::process
    E --> H(处理数据):::process
    G --> H
    H --> I(结束MPI):::process
    I --> J([结束]):::startend

这个流程图展示了MPI集体通信中的广播和收集操作的基本流程。首先,程序开始后初始化MPI环境,然后根据需求选择广播或收集操作。如果选择广播,根进程调用 MPI_Bcast 发送数据,所有进程接收数据;如果选择收集,所有进程发送数据,根进程调用 MPI_Gather 收集数据。最后,所有进程处理数据,结束MPI环境。

3.2 C与Fortran通信流程

下面是一个mermaid格式的流程图,展示了C语言调用Fortran例程的基本流程:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B(编写C代码):::process
    B --> C(编写Fortran代码):::process
    C --> D(编译Fortran代码):::process
    B --> E(编译C代码):::process
    D --> F(链接C和Fortran代码):::process
    E --> F
    F --> G(运行程序):::process
    G --> H{是否成功}:::decision
    H -->|是| I([结束]):::startend
    H -->|否| J(检查错误):::process
    J --> B

这个流程图展示了C语言调用Fortran例程的基本流程。首先,分别编写C代码和Fortran代码,然后分别编译这两种代码。接着,将编译后的代码进行链接,运行程序。如果运行成功,程序结束;如果运行失败,检查错误并重新编写代码。

4. 总结与操作建议

4.1 MPI操作总结

  • 点对点通信 MPI_Sendrecv_replace 用于发送和接收数据并替换缓冲区内容。
  • 集体通信 :包括广播、收集、散射、归约等操作,不同的操作函数适用于不同的场景,如 MPI_Bcast 用于广播, MPI_Gather 用于收集数据。
  • 通信器和组操作 :可以对通信器和组进行比较、创建、释放等操作,如 MPI_Comm_compare 比较通信器, MPI_Group_create 创建组。
  • 定时器和初始化 MPI_Wtick MPI_Wtime 用于计时, MPI_Init MPI_Finalize 用于启动和结束MPI环境。

4.2 Fortran与C通信总结

  • 参数传递 :Fortran通过地址传递参数,C通过值传递参数(数组除外)。
  • 数组存储 :Fortran数组在第一个索引上连续存储,C数组的第二个索引是“快速”索引。
  • 动态数组 :Fortran允许动态维度数组,C需要通过宏定义解决。
  • 复数类型 :Fortran支持复数类型,C在大多数情况下不支持。
  • 指针支持 :C有广泛的指针支持,Fortran的指针支持因编译器而异。

4.3 操作建议

4.3.1 MPI操作建议
  • 在使用MPI函数之前,务必调用 MPI_Init 进行初始化,并在程序结束时调用 MPI_Finalize 结束MPI环境。
  • 对于集体通信操作,确保所有进程都调用相应的函数,避免死锁。
  • 在使用自定义归约操作时,使用 MPI_Op_create 创建操作,并在不需要时使用 MPI_Op_free 释放操作。
4.3.2 C与Fortran通信建议
  • 在C语言调用Fortran例程时,注意Fortran例程名后加下划线(Cray平台除外)。
  • 编译和链接时,确保包含必要的库,如 libf2c.a libftn.a 等。
  • 处理Fortran的复数数组时,将其映射到C语言的二维浮点数数组中。

4.4 示例操作步骤

4.4.1 编写和运行MPI程序
  1. 编写MPI代码 :使用MPI函数编写并行程序,例如:
#include <stdio.h>
#include <mpi.h>

int main(int argc, char **argv) {
    int rank, size;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    printf("Hello from process %d of %d\n", rank, size);
    MPI_Finalize();
    return 0;
}
  1. 编译代码 :使用MPI编译器编译代码,例如:
mpicc -o hello hello.c
  1. 运行程序 :使用 mpirun 运行程序,例如:
mpirun -np 4 ./hello
4.4.2 C调用Fortran程序
  1. 编写C代码
#include <stdio.h>

int main() {
    int n = 2;
    unsigned char cl = 'C', c2;
    float x[2];
    void subr_(int*, char*, char*, float*);
    subr_(&n, &cl, &c2, x);
    printf("n=%d, cl=%c, c2=%c, x=%e, %e\n", n, cl, c2, x[0], x[1]);
    return 0;
}
  1. 编写Fortran代码
subroutine subr(n, cl, c2, x)
    integer n
    character*1 cl, c2
    real x(n)
    print *, "in subr: cl=", cl
    c2 = 'F'
    do i = 1, n
        x(i) = float(i)
    enddo
    return
end
  1. 编译和链接
gfortran -c subr.f90
gcc -c main.c
gcc -o main main.o subr.o -lgfortran
  1. 运行程序
./main

通过以上的总结和操作建议,希望能够帮助开发者更好地使用MPI进行并行计算,以及处理C与Fortran之间的通信问题。在实际应用中,根据具体需求选择合适的函数和方法,确保程序的正确性和高效性。

此文档描述了Fortranmpi的使用。 Fortran語言 1 MPI 平行計算程式設計 1 第一章 前言 5 1.1 MPI 平行計算軟體 6 1.2 國家高速網路與計算中心的平行計算環境 7 1.3 在IBM 電腦系統上如何使用MPI 8 1.3.1 IBM 電腦系統的MPI Fortran程式編譯指令 8 1.3.2 IBM 電腦系統的 Job command file 8 1.3.3 IBM 電腦系統的平行程式的執行指令 11 1.4 在PC Cluster上如何使用MPI 13 1.4.1 PC Cluster上的MPI Fortran程式編譯指令 13 1.4.2 PC Cluster 上的 Job command file 14 1.4.3 PC Cluster 上的平行程式執行指令 15 第二章 無邊界資料交換的平行程式 16 2.1 MPI 基本指令 17 2.1.1 mpif.h include file 17 2.1.2 MPI_INIT, MPI_FINALIZE 17 2.1.3 MPI_COMM_SIZE, MPI_COMM_RANK 18 2.1.4 MPI_SEND, MPI_RECV 19 2.2 無邊界資料交換的循序程式 T2SEQ 21 2.3 資料不切割的平行程式 T2CP 23 2.4 MPI_SCATTER,MPI_GATHER,MPI_REDUCE 28 2.4.1 MPI_SCATTER,MPI_GATHER 28 2.4.2 MPI_REDUCE, MPI_ALLREDUCE 30 2.5 資料切割的平行程式 T2DCP 32 第三章 需要邊界資料交換的平行程式 36 3.1 MPI_SENDRECV, MPI_BCAST 37 3.1.1 MPI_SENDRECV 37 3.1.2 MPI_BCAST 37 3.2 邊界資料交換的循序程式 T3SEQ 39 3.3 資料不切割的邊界資料交換平行程式 T3CP 40 3.4 資料切割的邊界資料交換平行程式(一) T3DCP_1 47 3.5 資料切割的邊界資料交換平行程式 (二) T3DCP_2 52 第四章 格點數不能整除的平行程式 57 4.1 格點數不能整除的循序程式 T4SEQ 58 4.2. MPI_SCATTERV、MPI_GATHERV 60 4.3 MPI_PACK、UNPACK、BARRIER、WTIME 62 4.3.1 MPI_PACK、MPI_UNPACK 62 4.3.2 MPI_BARRIER、MPI_WTIME 65 4.4 資料切割的平行程式 T4DCP 67 第五章 多維陣列的平行程式 72 5.1 多維陣列的循序程式 T5SEQ 73 5.2 多維陣列資料不切割的平行程式 T5CP 76 5.3 多維陣列末維資料切割的平行程式 T5DCP 85 5.4 與二維切割有關的 MPI 副程式 92 5.4.1 垂直座標圖示法則 (Cartesian Topology) 92 5.4.2 界定二維切割的 MPI 副程式MPI_CART_CREATE、 93 MPI_CART_COORDS、MPI_CART_SHIFT 93 5.4.3 定義固定間隔資料的 MPI 副程式 96 MPI_TYPE_VECTOR、MPI_TYPE_COMMIT 96 5.5 多維陣列末二維切割的平行程式 T5_2D 98 第六章 MPI程式的效率提昇 112 6.1 Nonblocking資料傳送 113 6.2 資料傳送的合併 122 6.3 以邊界資料計算取代邊界資料交換 126 6.4 輸出入資料的安排 128 6.4.1 事先切割輸入資料 128 6.4.2 事後收集切割過的輸出資料 131 第七章 導出的資料類別 133 7.1 導出的資料類別 134 7.2 陣列的轉換 139 7.3 兩方迴歸與管線法 149 第八章 多方依賴及SOR解法 155 8.1 四方依賴及SOR解法 156 8.2 黑白點間隔 SOR 解法 159 8.3 斑馬線 SOR 解法 168 8.4 八方依賴與四色點間隔SOR解法 175 第九章 有限元素法程式 183 9.1 有限元素法的循序程式 184 9.2 有限元素法的平行程式 187 附錄一 撰寫C語言的MPI程式 197 參考書目 200 Parallel Processing without Partition of 1-D Arrays 201 Parallel Processing with Partition of 1-D Arrays 202 Parallel on the 2nd Dimension of 2-D Arrays without Partition 203 Parallel on the 2nd Dimension of 2-D Arrays with Partition 204 Partition on the 3rd dimension of 3-D Arrays 205
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值