MPI入门:理解散发操作MPI_Scatterv

需积分: 42 15 下载量 141 浏览量 更新于2024-08-19 收藏 4.02MB PPT 举报
"散发(MPI_Scatterv)是Message Passing Interface (MPI)教程中的一个重要概念,它属于MPI的聚合通信类别。MPI是一种标准的并行编程接口,广泛用于高性能计算领域,特别是在分布式内存并行计算机上。本教程旨在介绍MPI的基本知识,以便程序员能够有效地利用这种工具进行并行编程。 预备知识部分首先概述了并行计算的概念,包括其目标(如减少计算时间和扩展计算规模)、并行机上的任务分解和子任务并行执行,以及并行计算涉及的多个层面,如并行计算机体系结构、并行算法、程序设计等。并行计算的基础条件包括并行计算机的存在、应用问题的并行度以及有效的并行编程。 并行计算机体系结构是理解MPI的关键,主要包括共享存储型(如UMA和NUMA)和分布式存储型(如DSM)。UMA模型支持均匀访问内存,所有处理器能平等地访问全局存储,而NUMA模型则有内存局部性,不同处理器访问不同内存的速度可能不同。DSM模型中,每个节点有自己的内存,只能本地访问,跨节点通信通常通过消息传递进行。 MPI的基础知识包括点对点通信(如发送和接收)、聚合通信(如Scatter和Gather操作,其中Scatterv是变长版本,适合向不同接收者发送不同大小的数据块),以及数据类型、进程组与通信器的管理。此外,了解拓扑结构有助于设计高效的通信路径,而并行I/O(I/O在并行环境中)是另一个重要的考虑因素,因为数据交换可能涉及大量的I/O操作。 在教学过程中,会参考张林波等人的《并行计算导论》、莫则尧等人的《消息传递并行编程环境MPI》以及都志辉等人的《高性能计算之并行编程技术》等教材,这些著作深入讲解了MPI的具体用法和实践技巧。学习MPI不仅是掌握一种通信手段,更是理解和应用并行计算思想的重要途径。 散发(MPI_Scatterv)操作是MPI教程中一个实用且基础的技能,它在实际并行程序设计中发挥着至关重要的作用,尤其是在处理大量数据的分发和处理场景。熟练掌握MPI有助于程序员构建高效的并行程序,提高计算性能和解决大规模问题的能力。"

请帮我修改这段代码的内存访问错误:#include <mpi.h> #include <stdlib.h> #include <stdio.h> int main(){ int rank, size; double starttime, endtime;//时间戳 int send_size=125;//125,1250,12500对应1kb、10kb、100kb信息 MPI_Init(0, 0); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); if (rank == 0) { // 初始化烫手山芋 char potato; potato=(char)malloc(send_sizesizeof(char));//分配内存空间 for(int i=0;i<send_size;i++){ potato[i]='a'; } // 发送烫手山芋给进程1 starttime = MPI_Wtime(); MPI_Send(&potato, send_size, MPI_CHAR, 1, 0, MPI_COMM_WORLD); printf("%f时,进程%d将烫手山芋发送给进程%d\n",starttime, rank, rank + 1); // 接收烫手山芋从最后一个进程 MPI_Recv(&potato, send_size, MPI_CHAR, size - 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); endtime=MPI_Wtime(); printf("%f时,进程%d从进程%d接收到烫手山芋\n", endtime,rank, size - 1); free(potato); } else { // 接收烫手山芋从上一个进程 char potato; potato=(char)malloc(send_sizesizeof(char));//分配内存空间 MPI_Recv(&potato, send_size, MPI_CHAR, rank - 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); endtime=MPI_Wtime(); printf("%f时,进程%d从进程%d接收到烫手山芋\n", endtime,rank, rank - 1); // 传递烫手山芋到下一个进程 starttime = MPI_Wtime(); MPI_Send(&potato, send_size, MPI_CHAR, (rank + 1) % size, 0, MPI_COMM_WORLD); printf("%f时,进程%d将烫手山芋传递给进程%d\n",starttime, rank, (rank + 1) % size); free(potato); } MPI_Finalize(); }

2023-06-10 上传

改进以下代码:#include <stdio.h> #include <stdlib.h> #include <mpi.h> #define N 4000 #define TAG 0 void merge(int arr[], int l, int m, int r) { int i, j, k; int n1 = m - l + 1; int n2 = r - m; int L[4000], R[4000]; for (i = 0; i < n1; i++) L[i] = arr[l + i]; for (j = 0; j < n2; j++) R[j] = arr[m + 1 + j]; i = 0; j = 0; k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } void mergeSort(int arr[], int l, int r) { if (l < r) { int m = l + (r - l) / 2; mergeSort(arr, l, m); mergeSort(arr, m + 1, r); merge(arr, l, m, r); } } int main(int argc, char** argv) { int rank, size; int i, j, k; int A[N], B[N]; int block_size, start, end; double start_time, end_time; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); block_size = N / size; start = rank * block_size; end = start + block_size - 1; if (rank == size - 1) { end = N - 1; } if (rank == 0) { printf("Generating random array...\n"); for (i = 0; i < N; i++) { A[i] = rand() % 100000; } printf("Sorting array...\n"); } MPI_Barrier(MPI_COMM_WORLD); start_time = MPI_Wtime(); MPI_Scatter(A, block_size, MPI_INT, &B[start], block_size, MPI_INT, 0, MPI_COMM_WORLD); mergeSort(B, start, end); for (i = 0; i < size; i++) { if (rank == i) { MPI_Send(&B[start], block_size, MPI_INT, (rank + 1) % size, TAG, MPI_COMM_WORLD); } else if (rank == (i + 1) % size) { MPI_Recv(&B[start], block_size, MPI_INT, i, TAG, MPI_COMM_WORLD, &status); } } MPI_Barrier(MPI_COMM_WORLD); end_time = MPI_Wtime(); if (rank == 0) { printf("Writing result to file...\n"); FILE* fp; errno_t err; err = fopen_s(&fp, "sorted_array.txt", "w"); for (i = 0; i < N; i++) { fprintf(fp, "%d\n", B[i]); } fclose(fp); printf("Done!\n"); printf("Time used: %.6f seconds\n", end_time - start_time); } MPI_Finalize(); return 0; }

2023-05-30 上传