MPI并行计算的基本介绍和使用

文章目录

  • MPI
    • 基本概念
    • 一般实现
    • 操作分类
    • 基本语句
      • windows下使用Microsoft MPI 示例
    • 点对点通信
      • 标准通信
      • 缓存通信
      • 同步通信
      • 就绪通信
    • MPI组通信
      • 广播 - 一对多
      • 收集
      • 散发
      • 组收集
      • 归约(reduce)
        • 归约并散发

MPI

基本概念

MPI(Message Passin Interface 消息传递接口)是一种消息传递编程模型,最终目的是服务于进程间通信。

MPI是一种标准或者规范的代表,不特指某一个对它具体的实现

MPI是一个库,不是一门语言

一般实现

层次说明
MPI通过ADI层提供的服务和平台无关的算法、数据结构实现MPI的标准接口
ADI通过底层通信库提供的API实现,把实现后的接口封装成一类抽象设备,上一层基于不同的硬件通信平台,选择不同的抽象设备
底层通道API通常由操作系统或者特定网络产品生产商提供

操作分类

MPI操作是由MPI库为建立和启用数据传输和/或同步而执行的一系列步骤

它包括四个阶段:初始化、开始、完成和释放

内部参数名称和概念

  • 序号:即进程的标识,是用来在一个进程组或者一个通信器中标识一个进程。是唯一的
  • 通信域:它描述了一组可以相互通信的进程以及他们之间的连接关系等信息。MPI所有通信必须在某个通信器中进行。
  • 消息:MPI程序中在进程间传递的数据。它由通信器、原地址、目的地之、消息标签和数据构成
  • 通信:通信是指在进程之间进行消息的收发、同步等操作
  • 缓冲区:在用户应用程序中定义的用于保存发送和接收数据的地址空间

基本语句

  • MPI_Init(int **argc, char ***argv)

完成MPI程序初始化工作,通过获取main函数的参数,让每一个MPI进程都能获取到main函数

  • MPI_Comm_rank(MPI_comm comm, int *rank)

用于获取调用进程在给定进程通信域中的进程标识号

  • MPI_Comm_size(MPI_comm comm, int *size)

调用返回给定的通信域中所包含的进程总数

  • MPI_Finalize(void)

清除全部MPI环境

windows下使用Microsoft MPI 示例

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <mpi.h>#define N 10int main(int argc, char **argv)
{int size, rank;int *send;int *recv;int i = 0;MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &size);MPI_Comm_rank(MPI_COMM_WORLD, &rank);send = new int[size * N];recv = new int[N];if(rank == 0){for(i = 0; i < size * N; i++){send[i] = i;}}MPI_Scatter(send, N, MPI_INT, recv, N, MPI_INT, 0, MPI_COMM_WORLD);std::printf("-------------------------rank = %d\n", rank);std::printf("-------------------------size = %d\n", size);for(int i = 0; i < N; i++){std::printf("recv buffer[%d] = %d \n", i, recv[i]);}std::printf("---------------------------------------\n");delete[] send;delete[] recv;MPI_Finalize();return 0;
}

运行

"C:\Program Files\Microsoft MPI\Bin\mpiexec.exe" -n 4 MPITest.exe

输出

-------------------------rank = 2
-------------------------size = 4
recv buffer[0] = 20 
recv buffer[1] = 21 
recv buffer[2] = 22 
recv buffer[3] = 23 
recv buffer[4] = 24 
recv buffer[5] = 25 
recv buffer[6] = 26 
recv buffer[7] = 27 
recv buffer[8] = 28 
recv buffer[9] = 29 
---------------------------------------
-------------------------rank = 3
-------------------------size = 4
recv buffer[0] = 30 
recv buffer[1] = 31 
recv buffer[2] = 32 
recv buffer[3] = 33 
recv buffer[4] = 34 
recv buffer[5] = 35 
recv buffer[6] = 36 
recv buffer[7] = 37 
recv buffer[8] = 38 
recv buffer[9] = 39 
---------------------------------------
-------------------------rank = 0
-------------------------size = 4
recv buffer[0] = 0 
recv buffer[1] = 1 
recv buffer[2] = 2 
recv buffer[3] = 3 
recv buffer[4] = 4 
recv buffer[5] = 5 
recv buffer[6] = 6 
recv buffer[7] = 7 
recv buffer[8] = 8 
recv buffer[9] = 9 
---------------------------------------
-------------------------rank = 1
-------------------------size = 4
recv buffer[0] = 10 
recv buffer[1] = 11 
recv buffer[2] = 12 
recv buffer[3] = 13 
recv buffer[4] = 14 
recv buffer[5] = 15 
recv buffer[6] = 16 
recv buffer[7] = 17 
recv buffer[8] = 18 
recv buffer[9] = 19 
---------------------------------------

点对点通信

MPI通信的模式:

发送操作:

  • MPI_SEND 标准通信
  • MPI_BSEND 缓存通信
  • MPI_SSEND 同步通信
  • MPI_RSEND 就绪通信

接收操作:

  • MPI_RECV

标准通信

MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm);
MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, status)

其中: buf 数据地址 count 数据个数 datatype 数据类型 source 原进程号 dest 目的进程号 tag进程标识 comm 通信域 status 状态

任意源和任意标识: MPI_ANY_SOURCE(标识任何继承发送的消息都可以接收) MPI_ANY_TAG(标识任何tag都可以接收)

  • MPI_ABORT(comm, errorcode) comm 退出进程所在的通信域 errorcode 返回到所嵌环境的错误码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <mpi.h>#define N 10int main(int argc, char **argv)
{int size, rank;int flag, rval, i;int buffer_1, recv_1;int buffer_2, recv_2;MPI_Status status, status1, status2, status3, status4;int src = 0;int dest = 1;MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &size);MPI_Comm_rank(MPI_COMM_WORLD, &rank);if(size != 2){printf("**这个程序使用了不是两个进程 %d**\n", size);MPI_Abort(MPI_COMM_WORLD, 1);}if(rank == src){buffer_1 = 200;buffer_2 = 20000;printf("standard MPI_Send\n");MPI_Send(&buffer_1, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);MPI_Send(&buffer_2, 1, MPI_INT, dest, 2, MPI_COMM_WORLD);printf("MPI_Send %d data, tag = 1\n", buffer_1);printf("MPI_Send %d data, tag = 2\n", buffer_2);}else if(rank == dest){MPI_Recv(&recv_1, 1, MPI_INT, src, 1, MPI_COMM_WORLD, &status3);MPI_Recv(&recv_2, 1, MPI_INT, src, 2, MPI_COMM_WORLD, &status4);printf("MPI_Recv %d data, tag = 1\n", recv_1);printf("MPI_Recv %d data, tag = 2\n", recv_2);}MPI_Finalize();return 0;
}

输出

standard MPI_Send
MPI_Send 200 data, tag = 1
MPI_Send 20000 data, tag = 2
MPI_Recv 200 data, tag = 1
MPI_Recv 20000 data, tag = 2

缓存通信

并行程序员对标准通信模式不满意,希望能够对通信缓冲区进行直接控制。

并行程序员需要对通信缓冲区进行申请、使用和释放,通信缓冲区的合理与正确使用需要设计人员自己保证。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <mpi.h>#define N 10int main(int argc, char **argv)
{int rank;double recv;double *tmpbuffer;int size = 1;int bsize;double data = 100.00;MPI_Status status;int src = 0;int dest = 1;MPI_Init(&argc, &argv);
//    MPI_Comm_size(MPI_COMM_WORLD, &size);MPI_Comm_rank(MPI_COMM_WORLD, &rank);if(rank == 0){printf("MPI_BSend\n");MPI_Pack_size(size, MPI_DOUBLE, MPI_COMM_WORLD, &bsize);tmpbuffer = (double *) malloc(bsize + MPI_BSEND_OVERHEAD);MPI_Buffer_attach(tmpbuffer, bsize + MPI_BSEND_OVERHEAD);printf("BSend data\n");MPI_Bsend(&data, 1, MPI_DOUBLE, 1, 2000, MPI_COMM_WORLD);MPI_Buffer_detach(&tmpbuffer, &bsize);}else if(rank == 1){MPI_Recv(&recv, 1, MPI_DOUBLE, 0, 2000, MPI_COMM_WORLD, &status);printf("MPI_Recv %f data\n", recv);}MPI_Finalize();return 0;
}

输出

MPI_Recv 100.000000 data
MPI_BSend
BSend data

同步通信

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <mpi.h>#define N 10int main(int argc, char **argv)
{int size, rank;int act_size = 0;int flag, rval, i;int buffer, recv;int sbuffer, srecv;int ssbuffer, ssrecv;int buffer1, recv1;MPI_Status status, status1, status2, status3, status4;int count1, count2;int src = 0;int dest = 1;MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &size);MPI_Comm_rank(MPI_COMM_WORLD, &rank);if(size != 2){MPI_Abort(MPI_COMM_WORLD, 1);}if(rank == src){buffer = 100;buffer1 = 10000;ssbuffer = 20000;sbuffer = 200;MPI_Send(&ssbuffer, 1, MPI_INT, dest, 3, MPI_COMM_WORLD);MPI_Send(&sbuffer, 1, MPI_INT, dest, 4, MPI_COMM_WORLD);MPI_Ssend(&buffer, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);printf("MPI_Ssend %d data tag = 1\n", buffer);MPI_Ssend(&buffer1, 1, MPI_INT, dest, 2, MPI_COMM_WORLD);printf("MPI_Ssend %d data tag = 2\n", buffer1);}else if(rank == dest){MPI_Recv(&srecv, 1, MPI_INT, src, 3, MPI_COMM_WORLD, &status3);MPI_Recv(&ssrecv, 1, MPI_INT, src, 4, MPI_COMM_WORLD, &status4);MPI_Recv(&recv, 1, MPI_INT, src, 1, MPI_COMM_WORLD, &status1);printf("MPI_Recv %d data tag = 1\n", recv);MPI_Recv(&recv1, 1, MPI_INT, src, 2, MPI_COMM_WORLD, &status2);printf("MPI_Recv %d data tag = 2\n", recv1);}MPI_Finalize();return 0;
}

输出

MPI_Ssend 100 data tag = 1
MPI_Ssend 10000 data tag = 2
MPI_Recv 100 data tag = 1
MPI_Recv 10000 data tag = 2

就绪通信

就绪通信的特殊之处就在于它要求接收操作先于发送操作而被启动。因此,在一个正确的程序中,一个就绪发送能被一个标准发送替代,它对程序的语义没有影响,而对程序的性能有影响。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <mpi.h>#define N 10int main(int argc, char **argv)
{int size, rank;int next, prev;int tag, count;double buffer, recv;MPI_Status status;MPI_Request  request;MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &size);MPI_Comm_rank(MPI_COMM_WORLD, &rank);tag = 1;next = rank + 1;if(next >= size)  next = 0;if(size != 2){MPI_Abort(MPI_COMM_WORLD, 1);}if(rank == 0){printf("Rsend Tets\n");buffer = 6666.0f;MPI_Recv(MPI_BOTTOM, 0, MPI_INT, next, tag, MPI_COMM_WORLD, &status);printf("process %d post ready", rank);MPI_Rsend(&buffer, 1, MPI_DOUBLE, next, tag, MPI_COMM_WORLD);}else{printf("process %d recive call", rank);MPI_Irecv(&recv, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &request);MPI_Send(MPI_BOTTOM, 0, MPI_INT, next, tag, MPI_COMM_WORLD);MPI_Wait(&request, &status);printf("ready MPI_recv = %f\n", recv);printf("process %d receive rsend message form &d\n", rank, status.MPI_SOURCE);}MPI_Finalize();return 0;
}

输出

Rsend Tets
process 0 post ready
process 1 recive callready MPI_recv = 6666.000000
process 1 receive rsend message form &d

MPI组通信

点对点通信是一个发送方和一个接收方2个进程

组通信则是一对多,多对一,多对多的进程,进程数量不确定

组通信一般实现了三个功能:

  • 通信:通信功能主要完成组内数据的传输 - 广播,收集,散发,组收集,全互换
  • 同步:同步功能实现组内所有进程在特定的地点在执行进度上取得一致,同步功能是许多应用中必须提供的功能,组同喜还提供专门的调用以完成各个进程之间的同步,从而协调各个进程的进度和步伐
  • 计算:计算功能稍微复杂一点,要对给定的数据完成一定的操作

广播 - 一对多

  • 广播函数接口:MPI_Bcast(buffer, count, datatype, root, comm)

收集

  • MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm)

  • MPI_GatherV(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm)

散发

  • MPI_Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm)

  • MPI_SCATTERV(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcounts, recvtype, root, comm)

组收集

  • MPI_ALLGATHER(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm)

归约(reduce)

MPI_REDUCE 将组内每个进程输入缓冲区中的数据按给定的操作op进行运算,并将其结果返回到序列号为root的进程的输出缓冲区中。

MPI中已经定义好了一些操作,他们是为函数MPI_REDUCE和一些其他的相关函数,如MPI_ALLREDUCE, MPI_REDUCE_SCATTER和MPI_SCAN而定义的,这些操作用来设定相应的op

名字含义
MPI_MAX最大值
MPI_MIN最小值
MPI_SUM求和
MPI_PROD求积
MPI_LAND逻辑与
MPI_BAND按位与
MPI_LOR逻辑或
MPI_BOR按位或
MPI_LXOR逻辑异或
MPI_BXOR按位异或
MPI_MAXLOC最大值且相应位置
MPI_MINLOC最小值且相应位置
归约并散发

MPI_REDUCE_SCATTER 操作可以认为是MPI对每个归约操作的变形,它将结果分散到主内的所有进程中取,而不是仅仅归约到root进程中。

求PI

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <mpi.h>#define N 10double f(double x)
{return (4.0 / (1.0 + x*x));
}int main(int argc, char **argv)
{int done = 0, n, myid, numprocs, i;double PI25DT = 3.141592653589793238462643;double mypi, pi, h, sum, x;double startwtime = 0.0, endwtime;int namelen;MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &numprocs);MPI_Comm_rank(MPI_COMM_WORLD, &myid);if(myid == 0){n = 100;}startwtime = MPI_Wtime();MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);h = 1.0/(double)n;sum = 0.0;for(i = myid + 1; i <= n; i+= numprocs){x = h * ((double)i - 0.5);sum += f(x);}mypi = h * sum;MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);if(myid == 0){printf("pi is approximately %.16f, Error is %.16f\n", pi, fabs(pi - PI25DT));endwtime = MPI_Wtime();printf("time = %f", endwtime - startwtime);fflush(stdout);}MPI_Finalize();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/127325.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云安全-云原生基于容器漏洞的逃逸自动化手法(CDK check)

0x00 docker逃逸的方法种类 1、不安全的配置&#xff1a; 容器危险挂载&#xff08;挂载procfs&#xff0c;Scoket&#xff09; 特权模式启动的提权&#xff08;privileged&#xff09; 2、docker容器自身的漏洞 3、linux系统内核漏洞 这里参考Twiki的云安全博客&#xff0c;下…

【通关选择】upload-labs通关攻略(全)

前提条件&#xff1a; 1.文件能够成功上传到服务器 2.攻击者能够知道文件的上传路径 upload-labs靶场 Pass-01&#xff08; 前端验证&#xff09; 三种方法解决思路 1.禁用客户端JavaScript弹窗 2.通过burp抓包&#xff0c;修改后缀名 3.f12删除return filecheck&#xff0…

测试用例设计——WEB通用测试用例

现在项目做完了&#xff0c;我觉得还是有必要总结一下&#xff0c;学习到的内容。毕竟有总结才能有提高嘛&#xff01;总结一下通用的东西&#xff0c;不管什么项目基本都可能会遇到&#xff0c;有写地方也有重复的或者有的是按照个人的习惯来总结的不一定都对&#xff0c;有不…

【深度学习】pytorch——实现CIFAR-10数据集的分类

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 往期文章&#xff1a; 【深度学习】pytorch——快速入门 CIFAR-10分类 CIFAR-10简介CIFAR-10数据集分类实现步骤一、数据加载及预处理实现数据加载及预处理归一化的理解访问数据集Dataset对象Dataloader对象 二、…

HTML区块、布局

HTML区块&#xff1a; HTML可以通过<div> 和 <span>将元素组合起来。大多数HTML元素被定义为块级元素或内联元素。块级元素在浏览器显示时&#xff0c;通常会以新行来开始、结束&#xff1b;内联元素在显示时通常不会以新行开始。 HTML<div>元素是块级元素…

JavaWeb 怎么在servlet向页面输出Html元素?

service()方法里面的方法体&#xff1a; resp.setContentType("text/html;charsetutf-8");//获得输出流PrintWriter对象PrintWriter outresp.getWriter();out.println("<html>");out.println("<head><title>a servlet</title>…

docker部署minio并使用springboot连接

需求&#xff1a;工作中&#xff0c;在微信小程序播放时&#xff0c;返回文件流并不能有效的使用&#xff0c;前端需要一个可以访问的地址&#xff0c;springboot默认是有资源拦截器的&#xff0c;但是不适合生产环境的使用 可以提供使用的有例如fastdfs或者minio&#xff0c;这…

Qt实现的自定义登录框连接MySQL(完整的实现过程)

一.开始创建项目 1.创建Qt窗口应用项目: 2.输入文件名、选择项目将要保存的地址 3.构造系统选择qmake 4.类名使用默认的就好,点击继续完成项目的创建 5.创建好的项目如下 二.创建一个资源管理文件 三.创建一个登录对话框窗口 1.选择一个ui界面类 2.选择Dialog without Butt…

git生成gitee和github两个不同的公钥

配置多个公钥 Windows 用户建议使用 Windows PowerShell 或者 Git Bash&#xff0c;在 命令提示符 下无 cat 和 ls 命令。 1、生成公钥文件&#xff1a; 通过命令 ssh-keygen 生成 SSH Key&#xff1a; ssh-keygen -t rsa -C "Gitee SSH Key" -f ~/.ssh/gitee_be…

【Unity ShaderGraph】| 快速制作一个 抖动效果

前言 【Unity ShaderGraph】| 快速制作一个 抖动效果一、效果展示二、UV抖动效果三、应用实例 前言 本文将使用ShaderGraph制作一个抖动效果&#xff0c;可以直接拿到项目中使用。对ShaderGraph还不了解的小伙伴可以参考这篇文章&#xff1a;【Unity ShaderGraph】| Shader Gr…

dash--项目的前端展示简单基础

1.前置工作 创建虚拟环境&#xff1a; sudo apt-get install python3-venv # 安装 python3 -m venv venv # 在本目录下创建venv虚拟环境&#xff08;也是一个文件夹。如果用不到这个虚拟环境以后就rm -rf venv&#xff09; source venv/bin/activate # 激活虚拟环境临时使用清华…

【WIFI】设置界面无法打开WiFi

一般这类问题优先检查下WIFI的ko文件是否加载成功 查看开机抓的kernel log可以看到如下信息, 说明出现大量的ko文件加载失败 行 3207: <14>[ 12.831274] .(1)[1:init]init 23: [12809][0]Command insmod /vendor/lib/modules/fpsgo.ko action=boot (/vendor/etc/ini…

poi兴趣点推荐数据集介绍

介绍 foursquare数据集包含2153471个用户&#xff0c;1143092个场所&#xff0c;1021970个签到&#xff0c;27098490个社交关系以及用户分配给场所的2809581评级&#xff0c;我们常用的是根据NYC和TKY都是从该数据集中抽取出来的。 下载地址&#xff1a;https://sites.google.…

D盘清空了怎么还原?3个恢复技巧大公开!

“由于我的文件一般都是保存在c盘的&#xff0c;d盘里没有什么文件&#xff0c;于是我在清理电脑时就把d盘清空了&#xff0c;但我突然想起有一个重要的文件夹在d盘中&#xff0c;现在还有办法找回这些文件吗&#xff1f;” D盘作为电脑的一个重要磁盘&#xff0c;有时候我们也…

损失函数总结(十三):RSELoss、MAPELoss

损失函数总结&#xff08;十三&#xff09;&#xff1a;RSELoss、MAPELoss 1 引言2 损失函数2.1 RSELoss2.2 MAPELoss 3 总结 1 引言 在前面的文章中已经介绍了介绍了一系列损失函数 (L1Loss、MSELoss、BCELoss、CrossEntropyLoss、NLLLoss、CTCLoss、PoissonNLLLoss、Gaussia…

day52【子序列】300.最长递归子序列 674.最长连续递增序列 718.最长重复子数组

文章目录 300.最长递增子序列674.最长连续递增序列718.最长重复子数组 300.最长递增子序列 题目链接&#xff1a;力扣链接 讲解链接&#xff1a;代码随想录链接 题意&#xff1a;给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而…

最新ai系统ChatGPT商业运营版网站源码+支持GPT4.0/支持AI绘画+已支持OpenAI GPT全模型+国内AI全模型+绘画池系统

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

5.1 运输层协议概述

思维导图&#xff1a; 前言&#xff1a; 第5章 运输层笔记 1. 概览 主要内容&#xff1a;介绍运输层协议的特点、进程间通信、端口、UDP和TCP协议、可靠传输、TCP报文段的首部格式、TCP的关键概念&#xff08;如滑动窗口、流量控制、拥塞控制和连接管理&#xff09;。重要性…

当函数参数为一级指针,二级指针

当函数参数为一级指针&#xff0c;二级指针 在讲述内容之前&#xff0c;先讲四点重要知识 1.当传入参数时&#xff0c;函数形参会立即申请形参的内存空间&#xff0c;函数执行完毕后&#xff0c;形参的内存空间立即释放掉。 1.指针是存放其他变量地址的变量。指针有自己的内…

任正非说:人家问我:“你怎么一天到晚游手好闲?”我说我是管长江的堤坝的。

你好&#xff01;这是华研荟【任正非说】系列的第26篇文章&#xff0c;让我们聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 一、我们不是靠人来领导这个公司&#xff0c;我们用规则的确定性来对付结果的不确定。人家问我&#xff1a;“你怎么一天到晚游…