(done) 自学 MPI (8) Exercise 2

url: https://hpc-tutorials.llnl.gov/mpi/exercise_2/


Exercise 2

如下图是练习2的要求:
在这里插入图片描述

阻塞型

阻塞型代码:

#include "mpi.h"      // MPI头文件
#include <stdio.h>    // 标准输入输出头文件
#include <stdlib.h>   // 标准库头文件
#define  MASTER		0  // 定义主进程的rank为0

int main (int argc, char *argv[])
{
    // MPI相关变量声明
    int  numtasks,    // MPI任务总数(进程数)
         taskid,      // 当前任务的排名(进程ID)
         len,         // 处理器名称长度
         partner,     // 通信伙伴的进程排名
         message;     // 接收到的消息内容
    
    char hostname[MPI_MAX_PROCESSOR_NAME];  // 存储处理器名称的数组
    MPI_Status status;  // MPI状态对象,用于接收操作

    // 初始化MPI环境
    MPI_Init(&argc, &argv);
    // 获取当前进程在通信域中的排名(ID)
    MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
    // 获取通信域中的进程总数
    MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

    /* 需要偶数个进程才能正常运行 */
    if (numtasks % 2 != 0) {
       if (taskid == MASTER) 
          printf("Quitting. Need an even number of tasks: numtasks=%d\n", numtasks);
    } 
    else {
       // 主进程打印总进程数
       if (taskid == MASTER) 
          printf("MASTER: Number of MPI tasks is: %d\n",numtasks);

       // 获取并打印当前进程运行的处理器名称
       MPI_Get_processor_name(hostname, &len);
       printf ("Hello from task %d on %s!\n", taskid, hostname);

       /* 确定通信伙伴并进行消息交换 */
       // 前半部分进程(0 到 numtasks/2-1)的通信逻辑
       if (taskid < numtasks/2) {
         partner = numtasks/2 + taskid;  // 伙伴是后半部分的对应进程
         // 先发送自己的rank给伙伴
         MPI_Send(&taskid, 1, MPI_INT, partner, 1, MPI_COMM_WORLD);
         // 然后接收伙伴发送过来的rank
         MPI_Recv(&message, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &status);
       }
       // 后半部分进程(numtasks/2 到 numtasks-1)的通信逻辑
       else if (taskid >= numtasks/2) {
         partner = taskid - numtasks/2;  // 伙伴是前半部分的对应进程
         // 先接收伙伴发送过来的rank
         MPI_Recv(&message, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &status);
         // 然后发送自己的rank给伙伴
         MPI_Send(&taskid, 1, MPI_INT, partner, 1, MPI_COMM_WORLD);
       }

       /* 打印伙伴信息并退出 */
       printf("Task %d is partner with %d\n",taskid,message);
    }

    // 终止MPI环境
    MPI_Finalize();
    
    return 0; // 程序正常退出
}

编译运行命令:

mpicc test.c -o test
mpirun -np 4 ./test

预期输出:

Hello from task 2 on <hostname>!
Hello from task 1 on <hostname>!
Hello from task 3 on <hostname>!
Task 1 is partner with 3
Task 3 is partner with 1
MASTER: Number of MPI tasks is: 4
Hello from task 0 on <hostname>!
Task 0 is partner with 2
Task 2 is partner with 0

非阻塞型

代码:

#include "mpi.h"      // MPI头文件
#include <stdio.h>    // 标准输入输出头文件
#include <stdlib.h>   // 标准库头文件
#define  MASTER		0  // 定义主进程的rank为0

int main (int argc, char *argv[])
{
int  numtasks,     // MPI任务总数(进程数)
     taskid,       // 当前任务的排名(进程ID)
     len;          // 处理器名称长度
char hostname[MPI_MAX_PROCESSOR_NAME];  // 存储处理器名称的数组
int  partner,      // 通信伙伴的进程排名
     message;      // 接收到的消息内容(伙伴的rank)
MPI_Status stats[2];   // MPI状态对象数组,用于Waitall操作
MPI_Request reqs[2];   // 非阻塞操作请求句柄数组

// 初始化MPI环境
MPI_Init(&argc, &argv);
// 获取当前进程在通信域中的排名(ID)
MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
// 获取通信域中的进程总数
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

/* 需要偶数个进程才能正常运行 */
if (numtasks % 2 != 0) {
   if (taskid == MASTER)
      printf("Quitting. Need an even number of tasks: numtasks=%d\n", numtasks);
   }

else {
   // 获取并打印当前进程运行的处理器名称
   MPI_Get_processor_name(hostname, &len);
   printf ("Hello from task %d on %s!\n", taskid, hostname);
   // 主进程打印总进程数
   if (taskid == MASTER)
      printf("MASTER: Number of MPI tasks is: %d\n",numtasks);

   /* 确定通信伙伴 */
   // 前半部分进程(0 到 numtasks/2-1)的伙伴是后半部分的对应进程
   if (taskid < numtasks/2) 
     partner = numtasks/2 + taskid;
   // 后半部分进程(numtasks/2 到 numtasks-1)的伙伴是前半部分的对应进程
   else if (taskid >= numtasks/2) 
     partner = taskid - numtasks/2;

   // 发布非阻塞接收操作:从伙伴进程接收一个整数
   MPI_Irecv(&message, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &reqs[0]);
   // 发布非阻塞发送操作:向伙伴进程发送自己的rank
   MPI_Isend(&taskid, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &reqs[1]);

   /* 等待所有非阻塞操作完成 */
   // 阻塞在此,直到发送和接收两个请求都完成
   MPI_Waitall(2, reqs, stats);

   /* 打印伙伴信息并退出*/
   printf("Task %d is partner with %d\n",taskid,message);
   }

// 终止MPI环境
MPI_Finalize();

return 0; // 程序正常退出
}

编译运行命令:

mpicc test.c -o test
mpirun -np 4 ./test

预期输出:

Hello from task 2 on <hostname>!
Hello from task 1 on <hostname>!
Hello from task 3 on <hostname>!
Task 1 is partner with 3
Task 3 is partner with 1
MASTER: Number of MPI tasks is: 4
Hello from task 0 on <hostname>!
Task 0 is partner with 2
Task 2 is partner with 0

[混合波束成形]基于深度学习的大规模天线阵列混合波束成形设计(Matlab代码、Python代码实现)内容概要:本文介绍了基于深度学习的大规模天线阵列混合波束成形的设计方法,并提供了Matlab和Python代码实现。该设计聚焦于5G及未来通信系统中的关键使能技术——混合波束成形,通过深度神经网络对复杂的信道状态信息(CSI)进行高效估计与波束成形矩阵优化,在保证通信性能的同时降低硬件成本与计算开销。文中详细阐述了算法模型构建、训练流程设计及仿真验证过程,展示了深度学习在通信物理层中的深度融合应用,尤其适用于毫米波大规模MIMO系统场景。; 适合人群:具备通信工程、信号处理或人工智能基础知识的研究生、科研人员及从事5G/6G技术研发的工程师;熟悉Matlab或Python编程,对深度学习和无线通信系统有一定实践经验者更为适宜。; 使用场景及目标:①研究深度学习在无线通信物理层中的应用,特别是CSI反馈压缩与波束成形优化;②复现先进混合波束成形算法,提升系统频谱效率与能效;③为学术论文复现、课题研究或工程项目开发提供可运行的代码参考与技术路线支持。; 阅读建议:建议读者结合文中提供的代码逐模块分析,重点关注神经网络结构设计与通信约束条件的融合方式,同时可扩展尝试不同网络架构或信道模型以深化理解。
STM32电机库无感代码注释无传感器版本龙贝格观测三电阻双AD采样前馈控制弱磁控制斜坡启动内容概要:本文档为一份名为《STM32电机库无感代码注释无传感器版本龙贝格观测三电阻双AD采样前馈控制弱磁控制斜坡启动》的技术资料,主要围绕基于STM32的永磁同步电机(PMSM)无传感器矢量控制系统的实现展开,详细注解了采用龙贝格观测器(Luenberger Observer)进行转子位置与速度估算的控制算法,涵盖三电阻采样、双通道ADC数据采集、电流环前馈补偿、弱磁扩速控制及斜坡启动策略等关键技术模块。该文档不仅提供了完整的控制逻辑说明,还深入解析了底层代码实现,适用于高精度、高性能电机控制系统的开发与学习。; 适合人群:具备一定嵌入式开发基础和电机控制理论知识的电气工程、自动化、机电一体化等相关专业的高校师生、科研人员及从事电机驱动开发的工程师;尤其适合希望深入理解无传感器电机控制算法及STM32平台实现的技术人员。; 使用场景及目标:①学习和掌握基于龙贝格观测器的无传感器电机控制原理与实现方法;②理解三电阻采样、双AD同步采集、前馈控制、弱磁控制和斜坡启动等关键环节的设计思路与代码实现;③用于高校课程设计、毕业设计、科研项目开发或工业级电机控制器的研发参考。; 阅读建议:建议读者结合STM32开发环境和电机控制实验平台进行代码阅读与调试,配合电机控制理论教材逐步理解各模块功能,重点关注观测器设计、坐标变换、PI调节器参数整定及ADC采样时序等核心部分,以实现理论与实践的有效结合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值