MPI并行编程实验报告_第1页
MPI并行编程实验报告_第2页
MPI并行编程实验报告_第3页
MPI并行编程实验报告_第4页
MPI并行编程实验报告_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

华中师范大学计算机学院姓名学号实验成绩计算机系统结构实验报告课 题:MPI并行编程实验 起讫日期:2012-05-20 2012-06-15组名:第四组院 系:计算机学院专 业:计算机科学与技术指导老师:XXX 教授2012年6月15日实验一Linux下基于MPI的hello程序设计Author:姓名一、MPICH并行计算库安装在Linux环境下安装MPICH执行环境,配置MPD.CONF, 完成实验室中临近机器间的并行配置。概要:以寝室四台计算机为例,设置IP(192.168.1.1192.168.1.4),更改主机名为node01,node02,node03, node04。(一)创建SSH信任连接1、更改/etc/hosts文件#vi /etc/hosts 打开hosts文件,更改如下: 127.0.0.1 localhost.localdomain localhost 192.168.1.1 node01 192.168.1.2 node02 192.168.1.3 node03 192.168.1.4 node042、在node01生成SSH秘钥对.#ssh-keygen -t rsa 一路回车即可产生.ssh文件,#ls -a 查看是否有.ssh文件夹3、进入.ssh目录#cd .ssh4、生成authorized_keys文件#cp id_rsa.pub authorized_keys 5、退出到root目录#cd .6、建立本身的信任连接#ssh node01 按提示输入yes(三个字母要打全)7、设置node02(node02的root目录下)#ssh-keygen -t rsa 生成.ssh文件夹#scp node01的IP:/root/.ssh/* /root/.ssh 拷贝node01上的.ssh文件夹覆盖本地的#scp node01的IP:/etc/hosts /etc/hosts 拷贝node01上的hosts文件覆盖本地的#ssh node01 提示处输入yes回车设置node03,node04的方法与node02相同8、确认四台机器的信任连接已建立对每个节点执行:#ssh node01#ssh node02#ssh node03#ssh node04在提示处输入yes回车,最后确定无需输入密码并且没有任何提示信息即可登陆(Last login:时间日期提示信息除外)(二)安装MPICH21、解压缩文件包#tar -zxvf mpich2-1.0.1.tar.gz2、创建安装目录#mkdir /usr/MPICH-instsll3、进入mpich2解压目录#cd mpich2-1.0.14、设置安装目录#./configure -prefix=/usr/MPICH-install5、编译#make6、安装#make install7、退出到root目录#cd .8、通过编辑.bashrc文件修改环境变量#vi .bashrc修改后的.bashrc文件如下:# .bashrc# User specific aliases and functions alias rm=rm -ialias cp=cp -ialias mv=mv -iPATH=$PATH:/usr/MPICH-install/bin 新增加的#Source global definitionsif -f /etc/bashrc ; then ./etc/bashrcfi9、测试环境变量设置#source /.bashrc#which mpd#which mpicc#which mpiexec#which mpirun10、修改/etc/mpd.conf文件,内容为secretword=myword#vi /etc/mpd.conf设置文件读取权限和修改时间#touch /etc/mpd.conf#chmod 600 /etc/mpd.conf11、创建主机名称集合文件/root/mpd.hosts#vi mpd.hosts文件内容如下:node01node02node03node04(三)配置NFS为了方便 MPICH 的安装及并行程序的运行,最好将 MPICH的安装目录及用户家目录通过 NFS 网络文件系统共享。对于仅包含几个结点的较小的集群系统,可以任意指定其中一个结点作为 NFS服务器。对较大的集群系统,应设定一个或数个结点专门用于文件服务,这些结点称为 I/O 结点,它们专门负责存储设备的管理,不参加计算。这里选择 node1 作为 NFS 服务器,将它的 /home 和/usr/MPICH-nstall目录输出给其他三个结点,相应的配置步骤如下。1、 以 root 身分登录到 node1 上,确保 node1 上安装了NFS 程序 (nfs-utils 包)。首先运行一遍下述命令来开启 NFS 服务: /sbin/chkconfig nfs on /sbin/chkconfig nfslock on /etc/init.d/nfslock restart /etc/init.d/nfs restart然后编辑文件 /etc/exports,在其中加入下面二行 (如果该文件不存在则创建一个新文件): /home 10.0.0.0/255.255.255.248(rw,async,no_root_squash) /usr/MPICH-install 10.0.0.0/255.255.255.248(rw,async,no_root_squash)做好上述修改后执行下面的命令: /sbin/exportfs -a便完成了 /home 和 /usr/local 目录的输出。2、 以root 身份登录到其余三个结点,在文件 /etc/fstab中加入下面两行: node1:/home /home nfs defaults 0 0 node1:/usr/local /usr/local nfs defaults 0 0并且运行一次下述命令: /sbin/chkconfig netfs on mount -t nfs -a完成上面的步骤后,node2,node3和node4 应该共享node1的/home和 /usr/MPICH-install 目录。可以在任何一个结点上用 df 命令来验证,例如: # df返回类似下面所示的结果: . . node1:/home 248632644 224028484 11974280 95% /home node1:/usr/MPICH-install 246966888 200888560 33533076 86% /usr/local(四)环境测试1、本地测试#mpd & 启动 #mpdtrace 观看启动机器#mpdallexit 退出2、通过mpd.hosts运行集群系统#mpdboot -n number -f mpd.hosts number为要起动的机器个数#mpdtrace #mpdallexit3、测试运行MPICH的例子程序#mpdboot -n 4 -f mpd.hosts 启动4台机器#mpiexec -n number /usr/MPICH-install/examples/cpi number为使用的进程数#mpdallexit二HELLO WORLD并行程序设计(一)程序源码:/*hello.c*/#include #include mpi.hint main( int argc, char *argv ) int rank; int size; MPI_Init( 0, 0 ); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); printf( Hello world from process %d of %dn, rank, size ); MPI_Finalize(); return 0;(二)程序编译$mpicc o hello hello.c(三)运行结果$mpdboot n -f mpd.hosts$mpiexec n ./hello(四)实验心得:基本上和vc运行是一样的,只是环境不一样,编译时要用mpicc o hello hello.c运行时要用mpiexec n ./hello,错误多错几次口令也就背下来了,当让,在运行框里可以看出我刚开始忘了建自己的目录就想开始编辑程序。实验二对等模式的MPI程序设计Author:姓名一、实验目的:掌握MPI并行程序设计的基本思想和主要编程方法,编写一个具有对等模式的MPI程序,实现各进程的对等。二、基本概念:所谓对等模式,就是说MPI程序的各个进程的功能、地位相同或相近, MPI程序的代码也应该是相近的,所不同的只是处理的对象和操作的数据,比如MPI程序让各个进程同时对一个数组的不同部分并行赋初值,各个进程间的关系就是典型的对等关系。三、实验环境: MPICH 2 Windows 7四、模块说明:Jacobi叠代为了并行求解,这里将参加迭代的数据按列进行分割,并假设一共有4个进程同时并行计算,数据的分割结果如下图所示。Jacobi迭代的数据划分及其与相应进程的对应捆绑发送接收捆绑发送和接收操作把发送一个消息到一个目的地和从另一个进程接收一个消息合并到一个调用中,源和目的可以是相同的。捆绑发送接收操作虽然在语义上等同于一个发送操作和一个接收操作的结合,但是它可以有效地避免由于单独书写发送或接收操作时,由于次序的错误而造成的死锁。这是因为该操作由通信系统来实现,系统会优化通信次序,从而有效地避免不合理的通信次序,最大限度避免死锁的产生。捆绑发送接收操作是不对称的,即一个由捆绑发送接收调用发出的消息可以被一个普通接收操作接收,一个捆绑发送接收调用可以接收一个普通发送操作发送的消息。该操作执行一个阻塞的发送和接收,接收和发送使用同一个通信域,但是可能使用不同的标识。发送缓冲区和接收缓冲区必须分开,他们可以是不同的数据长度和不同的数据类型。虚拟进程虚拟进程(MPI_PROC_NULL)是不存在的假想进程,在MPI中的主要作用是充当真实进程通信的目或源,引入虚拟进程的目的是为了在某些情况下编写通信语句的方便。当一个真实进程向一个虚拟进程发送数据或从一个虚拟进程接收数据时,该真实进程会立即正确返回,如同执行了一个空操作。在很多情况下为通信指定一个虚拟的源或目标是非常方便的,这不仅可以大大简化处理边界的代码,而且使程序显得简洁易懂。在捆绑发送接收操作中经常用到这种通信手段。一个真实进程向虚拟进程MPI_PROC_NULL发送消息时会立即成功返回;一个真实进程从虚拟进程MPI_PROC_NULL的接收消息时也会立即成功返回,并且对接收缓冲区没有任何改变。 五、程序设计:Jacobi叠代的实现program mainimplicit noneinclude mpif.hinteger totalsize,mysize,stepsparameter (totalsize=16)C 定义全局数组的规模parameter (mysize=totalsize/4,steps=10)integer n, myid, numprocs, i, j,rcreal a(totalsize,mysize+2),b(totalsize,mysize+2)C 定义局部数组integer begin_col,end_col,ierrinteger status(MPI_STATUS_SIZE)call MPI_INIT( ierr )call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )print *, Process , myid, of , numprocs, is aliveC 数组初始化do j=1,mysize+2do i=1,totalsizea(i,j)=0.0end doend doif (myid .eq. 0) thendo i=1,totalsizea(i,2)=8.0end doend ifif (myid .eq. 3) thendo i=1,totalsizea(i,mysize+1)=8.0end doend ifdo i=1,mysize+2a(1,i)=8.0a(totalsize,i)=8.0end doC Jacobi 迭代部分do n=1,stepsC 从右侧的邻居得到数据if (myid .lt. 3) thencall MPI_RECV(a(1,mysize+2),totalsize,MPI_REAL,myid+1,10,*MPI_COMM_WORLD,status,ierr)end ifC 向左侧的邻居发送数据if (myid .gt. 0) ) thencall MPI_SEND(a(1,2),totalsize,MPI_REAL,myid-1,10,* MPI_COMM_WORLD,ierr)end if C 向右侧的邻居发送数据if (myid .lt. 3) thencall MPI_SEND(a(1,mysize+1),totalsize,MPI_REAL,myid+1,10,* MPI_COMM_WORLD,ierr)end ifC 从左侧的邻居接收数据if (myid .gt. 0) thencall MPI_RECV(a(1,1),totalsize,MPI_REAL,myid-1,10,* MPI_COMM_WORLD,status,ierr)end ifbegin_col=2end_col=mysize+1if (myid .eq. 0) thenbegin_col=3endifif (myid .eq. 3) thenend_col=mysizeendifdo j=begin_col,end_coldo i=2,totalsize-1b(i,j)=(a(i,j+1)+a(i,j-1)+a(i+1,j)+a(i-1,j)*0.25end doend dodo j=begin_col,end_coldo i=2,totalsize-1a(i,j)=b(i,j)end doend doend dodo i=2,totalsize-1print *, myid,(a(i,j),j=begin_col,end_col)end docall MPI_Finalize(rc)end捆绑发送接收MPI_SENDRECV(sendbuf,sendcount,sendtype,dest,sendtag,recvbuf,recvcount,recvtype, source,recvtag,comm,status)IN sendbuf IN sendcount IN sendtype IN dest IN sendtag OUT recvbuf IN recvcount IN recvtype IN source IN recvtag IN comm OUT status 发送缓冲区起始地址(可选数据类型)发送数据的个数(整型) 发送数据的数据类型(句柄) 目标进程标识(整型) 发送消息标识(整型) 接收缓冲区初始地址(可选数据类型) 最大接收数据个数(整型) 接收数据的数据类型(句柄) 源进程标识(整型) 接收消息标识(整型) 通信域(句柄) 返回的状态(status) int MPI_Sendrecv(void *sendbuf, int sendcount,MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status)MPI_SENDRECV(SENDBUF, SENDCOUNT, SENDTYPE, DEST, SENDTAG, RECVBUF, RECVCOUNT, RECVTYPE, SOURCE, RECVTAG, COMM, STATUS, IERROR) SENDBUF(*), RECVBUF(*)INTEGER SENDCOUNT, SENDTYPE, DEST, SENDTAG, RECVCOUNT, RECVTYPE,SOURCE, RECVTAG, COMM,STATUS(MPI_STATUS_SIZE), IERROR虚拟进程program mainimplicit noneinclude mpif.hinteger totalsize,mysize,stepsparameter (totalsize=16)parameter (mysize=totalsize/4,steps=10)integer n, myid, numprocs, i, j,rcreal a(totalsize,mysize+2),b(totalsize,mysize+2)integer begin_col,end_col,ierrinteger left,right,tag1,tag2integer status(MPI_STATUS_SIZE)call MPI_INIT( ierr )call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )print *, Process , myid, of , numprocs, is aliveC 数组初始化do j=1,mysize+2do i=1,totalsizea(i,j)=0.0end doend doif (myid .eq. 0) thendo i=1,totalsizea(i,2)=8.0end doend ifif (myid .eq. 3) thendo i=1,totalsizea(i,mysize+1)=8.0end doend ifdo i=1,mysize+2a(1,i)=8.0a(totalsize,i)=8.0end dotag1=3tag2=4C 设置当前进程左右两侧的进程标识if (myid .gt. 0) thenleft=myid-1elseleft=MPI_PROC_NULLend ifif (myid .lt. 3) thenright=myid+1elseright=MPI_PROC_NULLend ifC Jacobi 迭代do n=1,stepsC 从左向右平移数据call MPI_SENDRECV(a(1,mysize+1),totalsize,MPI_REAL,right,tag1,*a(1,1),totalsize,MPI_REAL,left,tag1,*MPI_COMM_WORLD,status,ierr)C 从右向左平移数据call MPI_SENDRECV(a(1,2),totalsize,MPI_REAL,left,tag2,*a(1,mysize+2),totalsize,MPI_REAL,right,tag2,*MPI_COMM_WORLD,status,ierr)begin_col=2end_col=mysize+1if (myid .eq. 0) thenbegin_col=3endifif (myid .eq. 3) thenend_col=mysizeendifdo j=begin_col,end_coldo i=2,totalsize-1b(i,j)=(a(i,j+1)+a(i,j-1)+a(i+1,j)+a(i-1,j)*0.25end doend dodo j=begin_col,end_coldo i=2,totalsize-1a(i,j)=b(i,j)end doend doend dodo i=2,totalsize-1print *, myid,(a(i,j),j=begin_col,end_col)end docall MPI_Finalize(rc)end实验三基于MPI计算值Author:姓名一、实验题目用 MPI 技术计算的值。二、实验目的熟悉 MPI 编程,加深对其编程的理解。三、实验环境Windows XP SP3。 运行 MPI(一)安装 MPI第一步:下载 MPI 软件包 得到文件: mpich2-1.4.1p1-win-x86-64.msi. 1.2.5.zip 第二步:安装 1、运行mpich2-1.4.1p1-win-x86-64.msi并按提示进程安装 目标目录:D:Program FilesMPICH,安装内容:全选 2、依照提示完成全部安装工作 第三步:验证安装是否正确完成 1、查看 D:Program FilesMPICH 目录是否存在 2、打开“任务管理器”中的“进程”选项卡,查看是否有一个 mpd.exe 进程。如果有说明安 装成功。以后每次启动系统,该进程将自动运行。第四步:采用相同的方法完成局域网内其它计算机的安装工作 要求:1、均为管理员账户 2、目标目录必须完全相同 第五步:注册(每台计算机都要进行)目的:将先前在每台计算机上申请的账号与密码注册到 MPICH 中去,以便 MPICH 在网络 环境中访问每台主机。 方法: 运行“C:Program FilesMPICHmpdbinMPIRegister.exe”, 输入账号及密码, 完成注册。 用户名和密码必须是有管理员权限的密码,否则在运行该软件的时候将会出错。 第六步:配置(每台计算机都要进行) 目的:让 MPI 程序能在多台机器上运行。 方法:开始-程序-MPICH-mpd-MPICH Configuration tool” (二)在 C 语言上如何编写并运行 MPI 程序第一步:设置 C 语言的编译环境 1、新建一个 Win32 Console Application 工程。 方法:File-New 2、打开工程设置对话框。 方法:Project-settings 或 Alt+F7 3、切换到 C/C+选项卡。首先选择“Win32 Debug”(的下拉框),再选择“Code Generation” (的下拉框) 再选择“Debug Multithreaded” , (的下拉框) 在“Project 。 Options”的文本框中显示“/MT”表示设置成功。 然后选择“Win32Release” (的下拉框) 重复上述步骤。 4、在 C/C+选项卡中选择“All Configurations”。(的下拉框)选择“Preprocessor” (的下拉框),在相关位置输入 MPICH 所附带的头文件的目录。 5、 Link 选项卡中, 在 选择“All Configurations”。 再选择“Input”在“Additionallibrary path”的文本框中输入 MPICH 所附带的库文件的目录。 6、 Link 选项卡中, 在 选择“All Configurations”。 (的下拉框) 然后再选择“General” , 然后在“Object/library modules” 的文本框中添加“ws2_32.lib”。点击“OK”。这时在 “Common Options” 中会出现“ws2_32.lib”。 7、在 Link 选项卡中,选择“Win32 Debug”。然后再选择“General”,然后在 “Object/library modules”的文本框中添加“mpichd.lib”。点击“OK”。这时在“Project Options”中会出现“mpichd.lib”。 8、 Link 选项卡中, 在 选择“Win32 Release”。 然后再选择“General” , 在“Object/library modules” 的文本框中添加“mpich.lib”。点击“OK”。这时在“Project Options” 中会出 现“mpich.lib”。第二步:编写程序并编译 1、输入程序 2、编译 第三步:运行 1、将执行文件拷贝至 MPIRun.exe 所在的目录 E:mpidjanahellohelloDebug 2、点击运行按钮运行程序四、源程序#include mpi.h #include #include double f(a) double a; return (4.0 / (1.0 + a*a); int main(argc,argv) int argc; char *argv; int done = 0, n=100, myid, numprocs, i; double PI25DT = 3.141592653589793238462643; double mypi, pi, h, sum, x, a,startwtime, endwtime; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid); if (myid = 0) startwtime = MPI_Wtime(); 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 %.16f, Error is %.16fn, pi, fabs(pi - PI25DT); endwtime = MPI_Wtime(); printf(wall clock time = %fn, endwtime-startwtime); MPI_Finalize(); 五、运行结果实验四高斯算法的MPI实现Author:姓名一、实验题目用 MPI 技术设计实现高斯算法。二、实验目的熟悉 MPI 编程,加深对其编程的理解,并能够使用MPI进行程序设计。三、实验环境Windows XP SP3。 运行 MPI四、源程序#include stdio.h #include stdlib.h #include mpi.h #include math.h #define a(x,y) ax*M+y #define b(x) bx #define A(x,y) Ax*M+y #define B(x) Bx #define floatsize sizeof(float) #define intsize sizeof(int) int M; int N; int m; float *A; float *B; double starttime; double time1; double time2; int my_rank; int p; int l; MPI_Status status; void fatal(char *message) printf(%sn,message); exit(1); void Environment_Finalize(float *a,float *b,float *x,float *f) free(a); free(b); free(x); free(f); int main(int argc, char *argv) int i,j,t,k,my_rank,group_size; int i1,i2; int v,w; float temp; int tem; float *sum; float *f; float lmax; float *a; float *b; float *x; int *shift; FILE *fdA,*fdB; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&group_size); MPI_Comm_rank(MPI_COMM_WORLD,&my_rank); p=group_size; if (my_rank=0) starttime=MPI_Wtime(); fdA=fopen(dataIn.txt,r); fscanf(fdA,%d %d, &M, &N); if (M != N-1) printf(the input is wrongn); exit(1); A=(float *)malloc(floatsize*M*M); B=(float *)malloc(floatsize*M); for(i = 0; i M; i+) for(j = 0; j M; j+) fscanf(fdA,%f, A+i*M+j); fscanf(fdA,%f, B+i); fclose(fdA); MPI_Bcast(&M,1,MPI_INT,0,MPI_COMM_WORLD); /* 0号处理机将M广播给所有处理机 */ m=M/p; if (M%p!=0) m+; f=(float*)malloc(sizeof(float)*(M+1); /* 各处理机为主行元素建立发送和接收缓冲区(M+1) */ a=(float*)malloc(sizeof(float)*m*M); /* 分配至各处理机的子矩阵大小为m*M */ b=(float*)malloc(sizeof(float)*m); /* 分配至各处理机的子向量大小为m */ sum=(float*)malloc(sizeof(float)*m); x=(float*)malloc(sizeof(float)*M); shift=(int*)malloc(sizeof(int)*M); if (a=NULL|b=NULL|f=NULL|sum=NULL|x=NULL|shift=NULL) fatal(allocate errorn); for(i=0;iM;i+) shifti=i; /* 0号处理机采用行交叉划分将矩阵A划分为大小为m*M的p块子矩阵,将B划分为大小 为m的p块子向量,依次发送给1至p-1号处理机 */ if (my_rank=0) for(i=0;im;i+) for(j=0;jM;j+) a(i,j)=A(i*p,j); for(i=0;im;i+) b(i)=B(i*p); if (my_rank=0) for(i=0;iM;i+) if (i%p)!=0) i1=i%p; i2=i/p+1; MPI_Send(&A(i,0),M,MPI_FLOAT,i1,i2,MPI_COMM_WORLD); MPI_Send(&B(i),1,MPI_FLOAT,i1,i2,MPI_COMM_WORLD); /* my_rank=0 */ else /* my_rank !=0 */ for(i=0;im;i+) MPI_Recv(&a(i,0),M,MPI_FLOAT,0,i+1,MPI_COMM_WORLD,&status); MPI_Recv(&b(i),1,MPI_FLOAT,0,i+1,MPI_COMM_WORLD,&status); time1=MPI_Wtime(); /* 开始计时 */ for(i=0;im;i+) /* 消去 */ for(j=0;jp;j+) if (my_rank=j) /* j号处理机负责广播主行元素 */ v=i*p+j; /* 主元素在原系数矩阵A中的行号和列号为v */ lmax=a(i,v); l=v; for(k=v+1;klmax) lmax=a(i,k); l=k; if (l!=v) /* 列交换 */ for(t=0;tm;t+) temp=a(t,v); a(t,v)=a(t,l); a(t,l)=temp; tem=shiftv; shiftv=shiftl; shiftl=tem; for(k=v+1;kM;k+) /* 归一化 */ a(i,k)=a(i,k)/a(i,v); b(i)=

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论