MSRA实习期间,我们科大班的同学又多了一门课:高性能计算。授课的是新教员Teng。第二周结束的时候Teng布置了一道习题:用MPI实现K-means 或者Qsort的并行程序。

其实大家的学习热情并不高。我也不例外,每天组里面都有任务,软件工程课还有活要干,都很忙。于是匆匆忙忙就写了个K-means的算法交了作业:

View Code

  1 #include<mpi.h>  2 #include<stdio.h>  3 #include<time.h>  4 #include<string.h>  5 #include<float.h>  6 #include<malloc.h>  7 #include<math.h>  8 #include<random>  9  10 #define D 4 11 #define K 4 12 #define N  100 13  14 const int round=100; 15 const float MAXF=9999; 16  17 typedef struct { 18     float  dim[D]; 19 }Point; 20  21 typedef struct { 22     float dim[D]; 23     int n; 24 }CenterFactor; 25  26 int main(int argc,char ** argv) 27 { 28     Point *data,center[K]; 29     int processRank,processNum; 30     int i,j,t; 31     int count; 32     int index; 33     float minn,dist; 34     int singleNum,leftNum; 35     MPI_Status mpistat; 36     MPI_Datatype pointType,oldType[1]; 37     int blockCounts[1]; 38     MPI_Aint offsets[1]; 39     CenterFactor *centerFactor,centerTmp; 40     MPI_Request mpireq; 41  42          43     MPI_Datatype centerType,oldTypeCenter[2]; 44     int blockCountsCenter[2]; 45     MPI_Aint offsetsCenter[2],extent; 46      47      48     MPI_Init(&argc,&argv); 49     MPI_Comm_size(MPI_COMM_WORLD,&processNum); 50     MPI_Comm_rank(MPI_COMM_WORLD,&processRank); 51      52  53     offsets[0]=0; 54     oldType[0]=MPI_FLOAT; 55     blockCounts[0]=D;     56     MPI_Type_struct(1,blockCounts,offsets,oldType,&pointType); 57     MPI_Type_commit(&pointType);  58      59     MPI_Address(&centerTmp,&offsetsCenter[0]); 60     MPI_Address(&centerTmp.n,&offsetsCenter[1]); 61     offsetsCenter[1]-=offsetsCenter[0]; 62     offsetsCenter[0]=0; 63     oldTypeCenter[0]=MPI_FLOAT; 64     blockCountsCenter[0]=D; 65     oldTypeCenter[1]=MPI_INT; 66     blockCountsCenter[1]=1; 67     MPI_Type_struct(2,blockCountsCenter,offsetsCenter,oldTypeCenter,&centerType); 68     MPI_Type_commit(&centerType); 69      70      71      72     printf("MPI program: processNum=%d , processRank=%d ",processNum,processRank); 73     fflush(stdout);  74     singleNum=N/(processNum-1); 75      76     if (processRank==0) 77     { 78         srand((unsigned int)time(NULL)); 79         data=(Point *)malloc(sizeof(Point)*(N)); 80         for (i=0;i<N;i++) 81         { 82             for (j=0;j<D;j++) 83             { 84                 data[i].dim[j]=rand()/100; 85             }             86         } 87         for (i=0;i<K;i++) 88         { 89             memcpy(center+i,data+i,sizeof(Point)); 90         }         91          92         MPI_Request *mpireqs = (MPI_Request*)malloc(sizeof(MPI_Request) * (processNum - 1)); 93         MPI_Status *mpistats = (MPI_Status*)malloc(sizeof(MPI_Status) * (processNum - 1)); 94         for (i=1;i<processNum;i++) 95         { 96             if (i==processNum) 97             { 98                 leftNum=N-singleNum*(processNum-2); 99             }100             else leftNum=singleNum;101             MPI_Isend(data+singleNum*(i-1),leftNum,pointType,i,55,MPI_COMM_WORLD,&mpireqs[i - 1]);102         }    103         ::MPI_Waitall(processNum - 1, mpireqs, mpistats);     104         free(mpistats);105         free(mpireqs);106         centerFactor=(CenterFactor*)malloc(sizeof(CenterFactor)*K*processNum);107 108     }109     else 110     {111         if (processRank==processNum-1)112         {113             leftNum=N-singleNum*(processNum-2);114         }115         else leftNum=singleNum;116         117         data=(Point *)malloc(sizeof(Point)*leftNum);118         MPI_Recv(data,leftNum,pointType,0,55,MPI_COMM_WORLD,&mpistat);119 120         centerFactor=(CenterFactor*)malloc(sizeof(CenterFactor)*K);121     }122     123     count=0;124     while(count++<round)125     {126         if (processRank==0)127         {128             MPI_Request *mpireqs = (MPI_Request*)malloc(sizeof(MPI_Request) * 2 * (processNum - 1));129             MPI_Status *mpistats = (MPI_Status*)malloc(sizeof(MPI_Status) * 2 * (processNum - 1));130             for (i=1;i<processNum;i++)131             {132                 MPI_Isend(center,K,pointType,i,55,MPI_COMM_WORLD,&mpireqs[i - 1]);133             }134 135             for (i=1;i<processNum;i++)136             {137                 MPI_Irecv(centerFactor+K*i,K,centerType,i,55,MPI_COMM_WORLD,&mpireqs[(processNum - 1) + (i - 1)]);138             }139 140             MPI_Waitall( 2 * (processNum - 1), mpireqs, mpistats ); 141             free(mpistats);142             free(mpireqs);143 144             for (i=0;i<K;i++)145             {146                 centerFactor[i].n=0;147                 for (j=0;j<D;j++)148                 {149                     centerFactor[i].dim[j]=0;150                 }151             }152 153             for (i=1;i<processNum;i++)154                 for (j=0;j<K;j++)155                 {156                     centerFactor[j].n+=centerFactor[K*i+j].n;157                     for (t=0;t<D;t++)158                     {159                         centerFactor[j].dim[t]+=centerFactor[K*i+j].dim[t];160                     }161                 }162 163             for (i=0;i<K;i++)164             {165                 //if (centerFactor[i])166                 for (j=0;j<D;j++)167                 {168                     if (centerFactor[i].n!=0)169                       centerFactor[i].dim[j]/=centerFactor[i].n;170                     center[i].dim[j]=centerFactor[i].dim[j];171                 }172             }173         }174         else 175         {176             MPI_Recv(center,K,pointType,0,55,MPI_COMM_WORLD,&mpistat);177             for (i=0;i<K;i++)178             {179                 centerFactor[i].n=0;180                 for (j=0;j<D;j++)181                 {182                     centerFactor[i].dim[j]=0;183                 }184             }185             186         187             for (i=0;i<leftNum;i++)188             {189                 minn=FLT_MAX;                190                 for (j=0;j<K;j++)191                 {192                     dist=0;193                     for (t=0;t<D;t++)194                     {195                         dist+=(center[j].dim[t]-data[i].dim[t])*(center[j].dim[t]-196 197 data[i].dim[t]);198                     }199                     dist=sqrt(dist);200                     if (dist<minn)201                     {202                         index=j;203                         minn=dist;204                     }                    205                 }206                 centerFactor[index].n++;207                 for (j=0;j<D;j++)208                 {209                     centerFactor[index].dim[j]+=data[i].dim[j];210                 }211             }212             MPI_Send(centerFactor,K,centerType,0,55,MPI_COMM_WORLD);213         }214         215         printf("Round %d\n",count);216         for (i=0;i<K;i++)217         {218             printf("Center %d: ",i);219             for (j=0;j<D;j++)220             {221                 printf("%lf ",center[i].dim[j]);222             }223             printf("\n");224         }    225     }226 227     free(data);228     free(centerFactor);229 230     MPI_Type_free(&pointType);231     MPI_Type_free(&centerType);232     MPI_Finalize();233     234 }

 当时还是回到宾馆,躺在床上敲的。满脑子只想着快点over,然后提交作业。没有注释,没有细分函数,简直就像一陀堆在一起的砖头。甚至连自己都不想再看这个dirty的程序了。

过了两天Teng给我发了feedback邮件。结果让我很惊讶。

没想到Teng会认真地阅读程序的每一行,然后仔细的给出每一点意见。他先表扬了我的几个优点,比如作业提交的最快,用到了自定义结构、非阻塞调用等,然后指出程序的不足,如在程序的那个地方需要加上free()函数释放内存,哪一行应该用MPI_Waitall() 而不是MPI_Wait() ,用MPI_Scatterv()和MPI_Reduce ()来代替逐个进程调用MPI_Send()可以大大提高效率。

一共有13个同学提交了程序,Teng 对每一个同学都认真的回复了.真不知道他在阅读我们的dirty的代码上花了多少时间。有人猜测,Teng给我批改花的时间不会少于我们写程序的时间。在科大呆了三年,从未碰到一个老师/助教会对一件事这么负责。我们老是说自己很忙,现在想想,“忙”只是一种借口,一种不知不觉中被我们当作偷懒的工具罢了。

在被Teng的态度感动的同时,也对自己草率应付的心态感到羞愧。何时才能一名优秀的程序员?或许我要做的第一步,就是时刻记得,写代码,要对得起自己,对得起别人。

转载于:https://www.cnblogs.com/rosting/archive/2011/11/14/2248952.html

时刻记住要做合格的程序员——一次高性能程序设计实验课后的反思相关推荐

  1. 什么样的程序员才能算是一个合格的程序员呢?

    合格的程序员不是根据代码的行数来判断的,代码敲得飞一般的速度,只能说是个不错的打字员. 程序是为解决实际问题而存在的,要解决生活中的实际问题,掌握基本的语言知识是前提,敏捷的思维才是最有效的保障,思想 ...

  2. 如何成为一个合格的程序员?

    想要成为一个合格的程序员,往往需要满足以下几点要求: 一.细心 对于很多程序员来说,写出来的代码可能这里因为不小心漏了什么,那里因为不小心没有测试出一个Bug,这里少个符号,哪里多个空格等等,因为马虎 ...

  3. 如果你是合格的程序员或者你认为自己是计算机科学家

    如果你认为自己应该是计算机科学家,那么,你应该做如下的事情: 1,你学的第一门语言应该是C++,第二门是汇编 2,你应该对数学的掌握不差于数学专业的比较差的学生,对于数论那些东西你也应该会 3,你应该 ...

  4. 如何招聘一个合格的程序员?

    如何招聘一个合格的程序员? 发表于2012-12-03 16:29| 11559次阅读| 来源TheNextWeb| 23 条评论| 作者张祺 招聘程序员 摘要:作者是ApeForest和Conten ...

  5. 怎样才算得上合格的程序员

    转自:http://blog.csdn.net/B9Q8e64lO6mm/article/details/78829370 最近同一部门另一个项目组的一位程序员被"主动离职"了,虽 ...

  6. 怎样才算得上合格的程序员,教你一招

    对于程序员而言,技术过关当然是非常重要的,这是硬实力.然而只会技术也是不行的,毕竟大多数的程序员还是要与人打交道,软实力也是不可或缺的.怎样才能算合格,我认为有以下几点: 扎实的基础 计算机领域是一个 ...

  7. 怎样成为一个合格的程序员

    成为程序员就意味着要开启程序生涯,开始敲代码,如果说做程序员仅仅为了高工资,那么就不必做了.一天天干坐着只为等工资那么奉劝你,另谋高就. 学编程应该在编程中感受到快乐,不然每天对着没有表情的字母,很是 ...

  8. 一个合格的程序员所具备的素质和修养

    程序员基本素质: 作一个真正合格的程序员,或者说就是可以真正合格完成一些代码工作的程序员,应该 具有的素质. 1:团队精神和协作能力 把它作为基本素质,并不是不重要,恰恰相反,这是程序员应该具备的最基 ...

  9. 《我也能做CTO之程序员职业规划》之十六:逆商

    <我也能做CTO之程序员职业规划 >之十六:逆商Adversity Quotient (=AQ) 本文选自<我也能做CTO之程序员职业规划 >一书 锐哥想在工作之余到小蔡学校进 ...

最新文章

  1. 5号发工资和25号发工资,真能看出公司是否靠谱?
  2. Python Django 多表设计OneToOneField/ManyToManyField/ForeignKey
  3. origin画图_把heatmap翻一转:imshow的origin和extent
  4. java executor_Java并发编程(08):Executor线程池框架
  5. python标准库os的方法listdir_使用python标准库快速修改文件名字
  6. Linux——umask使用详解
  7. 以下不属于时序逻辑电路的有_静态时序分析圣经翻译计划——附录B:SDF
  8. 如何重启apache2服务
  9. node.weiChat
  10. 如何稳定地使用 Google 搜索
  11. matlab位姿,matlab位姿解算的相关问题,求助求助!
  12. 怎么让联想计算机升级,如何刷bios,教您联想电脑如何刷bios
  13. mac M1 下安装docker 及相关镜像
  14. 计算机桌面的文件拒绝访问,文件或文件夹拒绝访问的解决方法
  15. 关于android百度导航不能出声音的解决办法
  16. Markdown数学公式语法、常用符号与字体
  17. 1034-乘积小于 K 的子数组
  18. 按摩界的“爱马仕”,拯救你的发际线,失眠、职业病通通消失,爽爆了!
  19. 2017夸专业计算机考研,2017跨专业考研有难度吗?
  20. 码元速率、数据速率、信道带宽、信道容量、载波的概念

热门文章

  1. 详细解析RxAndroid的使用方式
  2. 《深入理解Nginx》阅读与实践(一):Nginx安装配置与HelloWorld
  3. Andrew Ng机器学习公开课笔记 -- 朴素贝叶斯算法
  4. 第14讲 转换与比较指令
  5. 第8章 静态路由配置
  6. MOQL—筛选器(Selector)(三)
  7. Leetcode 687.最长同值路径
  8. 【前端】CSS使用总结
  9. springmvc web.xml和application.xml配置详情(附:完整版pom.xml)
  10. RabbitMQ学习之Publish/Subscribe(3)