20150327

1. 영어 기사 읽기
1) African-American Longevity Suffered after Great Migration, Scientific American
– But records show that migrants died at higher rates from cirrhosis and pulmonary illnesses, which are linked to drinking and smoking. (cirrhosis – 간경변, pulmonary – 폐의)
2) Germanwings Flight 9525 co-pilot deliberately crashed plane, officials say, CNN


2. SPEC CPU 2006 ROI 확인 중
어제에 이어 SPEC CPU 2006 ROI 확인.
5) gobmk
A. gprofile 결과 분석
gtp_main_loop이 전체 실행시간의 99.7%를 차지함. 함수명도 gtp_main_loop인 것을 보아, 핵심 루프인 듯 하다. 이 안의 while 루프가 ROI이다.
B. ROI

//./interface/gtp.c
/* Read filehandle gtp_input linewise and interpret as GTP commands. */
void
gtp_main_loop(struct gtp_command commands[], FILE *gtp_input)
{
  char line[GTP_BUFSIZE];
  char command[GTP_BUFSIZE];
  char *p;
  int i;
  int n;
  int status = GTP_OK;
//ROI
  while (status == GTP_OK) {
    /* Read a line from gtp_input. */
    if (!fgets(line, GTP_BUFSIZE, gtp_input))
      break; /* EOF or some error */

6) hmmer
A. gprofile 결과 분석
hmmer는 gprofile의 결과를 해석하기 힘들었다. 소스 코드에 정의된 main 함수가 많아서 읽기가 힘들기도 했다. gprofile의 결과를 보면, P7Viterbi 함수가 전체 실행의 99.7%를 차지함. 함수 자체에서 실행하는 시간이 오래 걸림. 하지만 gprofile의 결과를 기준으로 하지 않음. main 함수를 찾아, HMM을 찾아내는 루틴을 ROI로 잡음. hmmer의 main 함수에 주석이 잘 달려 있어서 ROI를 찾아내기가 어렵지 않았다.
B. ROI

//hmmsearch.c
  printf(   "per-domain score cutoff:    ");
  if (thresh.domT == -FLT_MAX) printf("[none]\n");
  else  {
    printf(">= %.1f", thresh.domT);
    if      (thresh.autocut == CUT_GA) printf(" [GA2]\n");
    else if (thresh.autocut == CUT_NC) printf(" [NC2]\n");
    else if (thresh.autocut == CUT_TC) printf(" [TC2]\n");
    else                               printf("\n");
  }
  printf(   "per-sequence Eval cutoff:   ");
  if (thresh.globE == FLT_MAX) printf("[none]\n");
  else                  printf("<= %-10.2g\n", thresh.globE);
    
  printf(   "per-domain Eval cutoff:     ");
  if (thresh.domE == FLT_MAX) printf("[none]\n");
  else                 printf("<= %10.2g\n", thresh.domE);
  printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");

  /*********************************************** 
   * Search HMM against each sequence
   ***********************************************/

                /* set up structures for storing output  */
  histogram = AllocHistogram(-200, 200, 100);  /* keeps full histogram */
  ghit      = AllocTophits(200);         /* per-seq hits: 200=lumpsize */
  dhit      = AllocTophits(200);         /* domain hits:  200=lumpsize */

//ROI
  if (pvm_support && do_pvm)
    main_loop_pvm(hmm, sqfp, &thresh, do_forward, do_null2, do_xnu, 
          histogram, ghit, dhit, &nseq);
  else if (threads_support && num_threads)
    main_loop_threaded(hmm, sqfp, &thresh, do_forward, do_null2, do_xnu, num_threads,
               histogram, ghit, dhit, &nseq);    
  else 
    main_loop_serial(hmm, sqfp, &thresh, do_forward, do_null2, do_xnu, 
             histogram, ghit, dhit, &nseq);

  /*********************************************** 
   * Process hit lists, produce text output
   ***********************************************/

  /* Set the theoretical EVD curve in our histogram using 
   * calibration in the HMM, if available. 
   */
  if (hmm->flags & PLAN7_STATS)
    ExtremeValueSetHistogram(histogram, hmm->mu, hmm->lambda, 
                 histogram->lowscore, histogram->highscore, 0);
  if (!thresh.Z) thresh.Z = nseq;       /* set Z for good now that we're done. */

7) sjeng
A. gprofile 결과 분석
run_autotest 함수가 전체 시간의 98.9%를 차지함. run_autotest에서는 think 함수를 호출하고, 이는 전체 시간의 98.9%를 차지함. think는 search, search는 search_root를 호출하는데 이것은 각각 98.8%를 차지함. run_autotest에서 반복해서 think 함수를 호출하므로 while 루프 앞을 ROI로 잡음.
B. ROI

//epd.c
void run_autotest(char *testset)
{
    FILE *testsuite;
    char readbuff[STR_BUFF];
        int searchdepth;
    rtime_t start, end;
            
    move_s comp_move;

    testsuite = fopen(testset, "r");

    if (testsuite == NULL) exit(EXIT_FAILURE);

    start = rtime();
//ROI
    while (fgets(readbuff, STR_BUFF, testsuite) != NULL)
    {   
        setup_epd_line(readbuff);
                root_to_move = ToMove;
                           
        clear_tt();
        initialize_hash();
     
        printf("\n");
        display_board(stdout, 1); 

        printf("EPD: %s\n", readbuff);

        if (fgets(readbuff, STR_BUFF, testsuite) == NULL) exit(EXIT_FAILURE);
        searchdepth = atoi(readbuff);
     
        printf("Searching to %d ply\n", searchdepth);
        maxdepth = searchdepth;

        fixed_time = INF;
        comp_move = think();
    }   
     
    end = rtime();
/*        printf("Total elapsed: %i.%02i seconds\n", rdifftime(end, start)/100,
                                       rdifftime(end, start)%100);
*/
    fclose(testsuite);
    exit(EXIT_SUCCESS);
}

8) libquantum
A. gprofile 결과 분석
quantum_exp_mod_n에서 실행 시간의 98.1%를 차지함. 이 함수 내부의 for loop이 ROI이다.
B. ROI

//expn.c
void 
quantum_exp_mod_n(int N, int x, int width_input, int width, quantum_reg *reg)
{
        
    int i, j, f;
        
        

    quantum_sigma_x(2*width+2, reg);
//ROI
    for (i=1; i<=width_input;i++){
        f=x%N;          //compute
        for (j=1;j<i;j++)
          {   
            f*=f;   //x^2^(i-1)
            f= f%N;
          }   
        mul_mod_n(N,f,3*width+1+i, width, reg);
        }   
    }   

9) h264ref
A. gprofile 결과 분석
main에서 encode_one_frame을 호출하며, encode_one_frame이 실행 시간의 99.6%를 차지함. encode_one_frame이 frame_picture 함수를 호출하고 이것이 전체의 96.8% 시간을 차지함(총 120번 호출). frame_picture 함수 내부에서 ROI를 잡고 싶었으나, frame_picture가 여러 번 호출되므로, 그냥 encode_one_frame 함수 내부에 ROI를 잡음.
B. ROI

//image.c
      rc_init_pict(1,0,1); 
      img->qp  = updateQuantizationParameter(0); 
                                                                                                                         
           
      pic_type = img->type;
      QP =0;    }    

    if( active_sps->frame_mbs_only_flag)      img->TopFieldFlag=0;

    if (input->GenerateMultiplePPS)
      active_pps = &PicParSet[0];
//ROI
    frame_picture (frame_pic, 0);
   
    if ((input->RDPictureIntra || img->type!=I_SLICE) && input->RDPictureDecision)
    {    
      rdPictureCoding();
    }

10) omnetpp
A. gprofile 결과 분석
TCmdenvApp::run가 전체 실행 시간의 98.8% 차지함. 이 함수는 TCmdenvApp::simulate를 호출하고, 이 함수는 실행 시간의 95.4% 차지함. TCmdenvApp::simulate 함수 내부에서 while 루프가 ROI이다.
B. ROI

//./libs/cmdenv/cmdenv.cc
void TCmdenvApp::simulate()
{
    startClock();
    sigint_received = false;
    try 
    {   
//ROI
        if (!opt_expressmode)
        {   
           ev.disable_tracing = false;
           while (true)
           {   
               cSimpleModule *mod = simulation.selectNextModule();
               ASSERT(mod!=NULL);

               // print event banner if neccessary
               if (opt_eventbanners)
               {   
                   printf( "** Event #%ld  T=%s.  (%s) %s (id=%d)\n",
                           simulation.eventNumber(),
                           simtimeToStr( simulation.simTime() ),
                           mod->className(),
                           mod->fullPath(),
                           mod->id()
                         );  
               }   

               // flush *between* printing event banner and event processing, so that
               // if event processing crashes, it can be seen which event it was
               if (opt_autoflush)
                   fflush(stdout);

               // execute event
               simulation.doOneEvent( mod );

               checkTimeLimits();
               if (sigint_received)
                   throw new cTerminationException("SIGINT or SIGTERM received, exiting");
           }   
        }   

11) astar
A. gprofile 결과 분석
regwayobj::createway 함수가 65.1%의 실행 시간을 차지한다. astar는 regwayobj::createway 함수와 wayobj::createway 함수를 여러 차례에 걸쳐 호출한다. 따라서 regwayobj::createway를 사용하는 루프에 진입하기 직전에 sync를 맞추면 된다.
B. ROI

//Library.cpp
#if !defined(SPEC_CPU)
  t2=time(nil);
  stat.createwaytime=difftime(t2,t1);
#else
  stat.createwaytime=0;
#endif /* !SPEC_CPU */


  t1=time(nil);
//ROI
  for (i=0; i<info.regwayqu; i++)
  {
    i32 reg1num,reg2num;
    regobjpt reg1p,reg2p;
    regobjppt wayar;
    i32 waylength;
    bool flcreate;
        
    reg1num=random1(regmng.rarp.elemqu-1);
    reg2num=random1(regmng.rarp.elemqu-1);

    reg1p=regmng.rarp[reg1num];
    if (reg1p->nb1ar.elemqu==0)
      continue;
    reg2p=regmng.rarp[reg2num];
    if (reg2p->nb1ar.elemqu==0)
      continue;

    wayar=nil;
    waylength=0;

    flcreate=regway.createway(reg1p,reg2p,wayar,waylength);
#if defined(SPEC_CPU)
      // jray: get rid of the FREE_NULL insure msgs
      if (wayar) free(wayar); 
#else
      free(wayar);
#endif

    if (flcreate)
    {   
      stat.regwaylength+=waylength;
      stat.regwayqu++;
    }   
  }

12) xalancbmk
A. gprofile 결과 분석
xsltMain 함수에서 97.5%, transform 함수에서 97.4%의 실행 시간을 차지한다. transform 함수는 재귀적으로 호출하는 것으로 보이며, 따라서 xsltMain에서 transform을 호출하기 직전 위치에서 sync한다.
B. ROI

//XalanExe.cpp
int
xsltMain(
            int     argc,
            char*   argv[])

{
    int theResult = -1; 

    XALAN_USING_XERCES(XMLPlatformUtils)
    
    // Call the static initializer for Xerces...
    XMLPlatformUtils::Initialize();
    
    // Initialize Xalan...
    XalanTransformer::initialize();
    
    {   
        // we need to read the params after the XMLPlatformUtils::Initialize(), because we may
        // need the local and the local dlls for usage of the Usage function
    
        // Set the maximum number of params as half of argc - 1.
        // It's actually argc - 2, but that could get us into negative
        // numbers, so don't bother.  Also, always add 1, in case
        // (argc - 1) / 2 is 0.
        Params  theParams((argc - 1) / 2 + 1); 
    
        if (getArgs(argc, argv, theParams) == false)
        {   
            Usage();
        }   
        else
        {   
            // Create a XalanTransformer instance...
            XalanTransformer    theTransformer;
    
            // Set any options...
 
                        // Perform validation
                        theTransformer.setUseValidation(true);

            theParams.setParams(theTransformer);
//ROI
            theResult = transform(theTransformer, theParams);

            if (theResult != 0)
            {   
                cerr << theTransformer.getLastError() << endl;
            }   
        }   
    }   

Floating Point Benchmarks

1) bwaves
A. gprofile 결과 분석
shell 함수가 100%의 실행 시간을 차지하고, bi_cgstab_block 함수를 호출한다. bi_cgstab_block 함수는 전체 실행 시간의 89.2%를 차지한다. 따라서 bi_cgstab_block 함수를 사용하기 전에 sync를 맞추면 된다. bi_cgstab_block 함수는 정해진 횟수만큼 반복하므로, 해당 루프 바로 앞에서 sync를 맞춘다.
B. ROI

C shell_lam.f
C Propagation in time



      time = 0.0d0

C ROI
      do n=1,ni
C     Time step definition

      cfll=0.1d0+(n-1.0d0)*cfl/20.0d0
      if (cfll.ge.cfl) cfll=cfl
      t8=0.0d0

      do k=1,nz
         do j=1,ny
            do i=1,nx
               t1=q(1,i,j,k)
               t2=q(2,i,j,k)/t1
               t3=q(3,i,j,k)/t1
               t4=q(4,i,j,k)/t1
               t5=(gm-1.0d0)*(q(5,i,j,k)-0.5d0*t1*(t2*t2+t3*t3+t4*t4))
               t6=dSQRT(gm*t5/t1)
               mu=gm*Pr*(gm*t5/t1)**0.75d0*2.0d0/Re/t1
               t7=((dabs(t2)+t6)/dx+mu/dx**2)**2 +
     1            ((dabs(t3)+t6)/dy+mu/dy**2)**2 +
     2            ((dabs(t4)+t6)/dz+mu/dz**2)**2
               t7=DSQRT(t7)
               t8=max(t8,t7)
            enddo
         enddo
      enddo
      dt=cfll / t8

2) gamess
A. gprofile 결과 분석
main에서 BRNCHX 함수를 호출하고, 이 함수는 실행 시간의 99.8%를 차지한다. 따라서 BRNCHX 함수 호출 이전 지점에서 sync한다.
B. ROI

c gamess.F
C                     CHECK IF PARALLEL CI IS ENABLED
      IF((CITYP.EQ.ALDET .OR. CITYP.EQ.FSODCI .OR. CITYP.EQ.GENCI
     *    .OR.  CITYP.EQ.ORMAS) .AND.  GOPARR) THEN 
         IF(MASWRK) WRITE(IW,9090) CITYP
         CALL ABRT 
      END IF
C
      IF (TIM .GE. TIMLIM) CALL ABRT 
C
C     IF RUNTYP.EQ.'SURFACE ', SCAN POTENTIAL ENERGY SURFACE FOR THE
C     RUNTYP GIVEN IN $SURF.  MOST RUNS CAN PROCEED DIRECTLY TO THE
C     BRANCHING OFF ROUTINE, TO DO THE RUNTYP SELECTED IN $CONTRL.
C
C ROI
      IF(RUNTYP.EQ.SURF) THEN 
         CALL SURFX
      ELSE 
         CALL BRNCHX(RUNTYP)
      END IF

3) milc
A. gprofile 결과 분석
update 함수에서 전체 실행 시간의 88.3%를 차지함. 여기서 eo_ermion_force를 호출하며 이는 53.6%의 실행 시간을 차지함. 따라서 update 함수의 for 루프 앞에서 sync를 맞추면 된다.
B. ROI

//update.c
int update()  {
int step, iters=0;
double final_rsq;
void predict_next_xxx(double *oldtime,double *newtime,double *nexttime);
double cg_time,old_cg_time,next_cg_time;    /* simulation time for last two CG's */
#ifdef HMC_ALGORITHM
double startaction,endaction,d_action();
double xrandom;
#endif

    /* refresh the momenta */
    ranmom();

/*DEBUG*/
/**grsource_imp(F_OFFSET(phi), mass, EVENANDODD);
ks_congrad(F_OFFSET(phi),F_OFFSET(xxx),mass,niter,rsqmin,EVENANDODD,&final_rsq);
checkmul();**/
/*ENDDEBUG*/
//ROI
    /* do "steps" microcanonical steps  */
    for(step=1; step <= steps; step++){
 
#ifdef PHI_ALGORITHM
        /* generate a pseudofermion configuration only at start*/
        if(step==1){grsource_imp(F_OFFSET(phi), mass, EVEN); old_cg_time = cg_time = -1.0e6;}

#ifdef HMC_ALGORITHM
        /* find action */
        /* do conjugate gradient to get (Madj M)inverse * phi */
        if(step==1){
            /* do conjugate gradient to get (Madj M)inverse * phi */
        iters += ks_congrad( F_OFFSET(phi), F_OFFSET(xxx), mass, 
                 niter, rsqmin, EVEN, &final_rsq );
        cg_time = 0.0;

            startaction=d_action();
            /* copy link field to old_link */
        gauge_field_copy( F_OFFSET(link[0]), F_OFFSET(old_link[0]));
        }   
#endif

4) zeusmp
A. gprofile 결과 분석
transprt 함수가 전체 실행 시간의 92.4%를 차지함. transprt 함수는 ct 함수를 150회 호출함. transprt 함수 내부에서 ROI를 잡고 싶지만, 루프가 어디에 있는지 코드를 분석해내지 못함. call transprt 앞에서 sync를 맞춤.
B. ROI

c zeusmp.F
CPS

c
c--------------------------  start of main loop  -----------------------
c
c Execution ends when INTCHK returns a value of 1 for ifsen(1).
c

1000  continue

      nsub = 1 

CPS

C
c
c Evaluate all non-advective terms in the evolution equations.
c
        call srcstep
c
c Compute the advection of all field variables.
c
c ROI
        call transprt
c
c Optional call user-supplied module.
c
        call empty
c
c Update the step counter and current time value.
c
        nhy   = nhy   + 1 
        time  = time  + dt
c

5) gromacs
A. gprofile 결과 분석
mdrunner에서 100%의 실행 시간을 차지함. 이 함수에서 호출하는 do_md 함수도 마찬가지로 100%의 실행시간을 차지함. do_md에서 do_force 함수를 7001번 호출한다. 따라서 do_force 함수를 호출하는 루프를 ROI로 잡으면 된다.
B. ROI

//md.c
  /* if rerunMD then read coordinates and velocities from input trajectory */
  if (bRerunMD) {              
    bNotLastFrame = read_first_frame(&status,opt2fn("-rerun",nfile,fnm),
                     &rerun_fr,TRX_NEED_X | TRX_READ_V);
    if (rerun_fr.natoms != mdatoms->nr)
      fatal_error(0,"Number of atoms in trajectory (%d) does not match the "
          "run input file (%d)\n",rerun_fr.natoms,mdatoms->nr);
  } 
  
  /* loop over MD steps or if rerunMD to end of input trajectory */
  bFirstStep = TRUE;           
  step = 0;
//ROI
  while ((!bRerunMD && (step<=parm->ir.nsteps)) ||  
     (bRerunMD && bNotLastFrame)) {  

6) cactusADM
A. gprofile 결과 분석
cactusADM은 코드 해석이 어려워 어려움을 겪었다. main 함수가 여러 곳에 정의되어 있었는데, 실제 main 함수는 ./Cactus/flesh.c인 것 같다(확신할 수는 없음). main 함수에서 호출하는 함수의 이름을 보고 초기화 루틴을 건너뛴 다음 ROI를 잡음.
B. ROI

//./Cactus/flesh.c
int main(int argc, char **argv)
{
  tFleshConfig ConfigData;

  /* Initialise any cactus specific stuff.
   */
  CCTKi_InitialiseCactus(&argc, &argv, &ConfigData);

  /* This is a (c-linkage) routine which has been registered by a thorn.
   */
  CCTK_Initialise(&ConfigData);

  /* This is a (c-linkage) routine which has been registered by a thorn.
   */
//ROI
  CCTK_Evolve(&ConfigData);

  /* This is a (c-linkage) routine which has been registered by a thorn.
   */
  CCTK_Shutdown(&ConfigData);

  /* Shut down any cactus specific stuff.
   */
  CCTKi_ShutdownCactus(&ConfigData);

  return 0;
}

7) leslie3d
A. gprofile 결과 분석
leslie3d는 한 개의 포트란 파일로 이루어져 있다. FLUXI, FLUXJ, FLUXK 함수를 반복적으로 호출하며 주요 연산을 수행한다. 따라서 while 루프 진입 이전에 sync하면 된다.
B. ROI

c tml.f
      TAU  = 0.0D0
      NADV = NSTART

      TIME_START = GET_TIME()
c ROI
      DO WHILE (NADV .LE. NEND .AND. TAU < TAUMAX)

         IF(MOD(NADV,ITIME) .EQ. 0 .OR. NADV .EQ. NSTART) CALL TMSTEP()

         TIME = TIME + DT 

         CALL ANALYSIS(TAU, DELM)
         WRITE(99,'(2F12.6)') TAU, DELM 

c         IF(MOD(NADV,ITIME) == 0) WRITE(6,10) NADV, DT, TIME, TAU, DELM
10       FORMAT(1X,'NADV = ',I7,' DT = ',E12.6, ' TIME = ',F10.6,
     >       ' TAU = ',F10.6,' DEL MOM = ', F10.6)

         NADV = NADV + 1

         IADD = MOD(NADV,2)
         JADD = MOD((NADV+IADD)/2,2)
         KADD = MOD(((2*JADD+IADD+NADV)/4),2)

         IF (IADD .EQ. 1) THEN 
            IBDD = 1
            ICDD = 0
         ELSE 
            IBDD = -1 
            ICDD = -2 
         END IF
         IF (JADD .EQ. 1) THEN 
            JBDD = 1
            JCDD = 0
         ELSE 
            JBDD = -1 
            JCDD = -2 
         END IF
         IF (KADD .EQ. 1) THEN 
            KBDD = 1
            KCDD = 0
         ELSE 
            KBDD = -1 
            KCDD = -2 
         END IF

         DO N = 1, 2 
            M = 3 - N
            NM1 = N - 1

            CALL FLUXI()

            CALL FLUXJ()

            CALL FLUXK()

8) namd
A. gprofile 결과 분석
ComputeList::runComputes 함수가 전체 실행 시간의 99.7%를 차지하며, 이 함수는 PairCompute::doWork와 SelfCompute::doWork를 호출한다. 따라서 ComputeList::runComputes 함수 내부에서 sync를 맞추면 된다.
B. ROI

//ComputeList.C
void ComputeList::runComputes(PatchList *patchList) {

  int i;
// ROI
  for ( i=0; i<numSelfComputes; ++i ) { 
    selfComputes[i].doWork(patchList);
  }

  for ( i=0; i<numPairComputes; ++i ) { 
    pairComputes[i].doWork(patchList);
  }

}

9) dealII
A. gprofile 결과 분석
Framework::run 함수가 전체 실행 시간의 99.6%를 차지함. 이 함수는 여러 함수를 호출하는데, 그 중에 solve_problem, output_solution, refine_grid가 많은 비중을 차지한다. 따라서 관련 루프가 ROI이다.
B. ROI

//step-14.cc
                   // Now that all objects are in  
                   // place, run the main loop. The
                   // stopping criterion is        
                   // implemented at the bottom of the
                   // loop.    
                   //          
                   // In the loop, first set the new
                   // cycle number, then solve the 
                   // problem, output its solution(s),
                   // apply the evaluation objects to
                   // it, then decide whether we want
                   // to refine the mesh further and
                   // solve again on this mesh, or 
                   // jump out of the loop.        
//ROI
  for (step=0; step<=n_steps; ++step) 
    {
      std::cout << "Refinement cycle: " << step 
        << std::endl;          
        
      solver->set_refinement_cycle (step);
      solver->solve_problem ();
      solver->output_solution ();     
  
      std::cout << "   Number of degrees of freedom="
        << solver->n_dofs() << std::endl;
      
      for (typename EvaluatorList::const_iterator
         e = descriptor.evaluator_list.begin();
       e != descriptor.evaluator_list.end(); ++e)
    {
      (*e)->set_refinement_cycle (step);
      solver->postprocess (**e);      
    };
  
        
      if (solver->n_dofs() < descriptor.max_degrees_of_freedom)
    solver->refine_grid ();    
      else
    break;
    };
  
                   // After the loop has run, clean up
                   // the screen, and delete objects
                   // no more needed:              
  std::cout << std::endl;      
  delete solver;               
  solver = 0;
} 

10) soplex
A. gprofile 결과 분석
soplex::SoPlex::solve 함수가 전체 실행 시간의 99.5%를 차지하며, 이 함수에서 leave 함수를 45000번 호출한다. 따라서 leave 함수를 호출하는 loop 앞에서 sync를 맞추면 된다.
B. ROI

//spxsolve.cc
   if (SPxBasis::status() == SPxBasis::OPTIMAL)
      setStatus(SPxBasis::REGULAR);   
  
   m_status   = RUNNING;       
   bool stop  = terminate();   
   leaveCount = 0;             
   enterCount = 0;             
  
//ROI
   while (!stop)
   {
      if (type() == ENTER)     
      {
         VERBOSE3({            
            std::cerr << "Enter iteration: " << iteration()
                      << ", Value = " << value()      
                      << ", Shift = " << shift() << std::endl;
         });

11) povray
A. gprofile 결과 분석
pov::Start_Non_Adaptive_Tracing 함수가 한 번 호출되면서 가장 많은 실행 시간을 갖는다. 내부에서 for loop를 돌며 pov::trace_pixel를 호출한다. 해당 루프 바로 앞에서 sync를 맞춘다.
B. ROI

//render.cpp
void Start_Non_Adaptive_Tracing()
{
  COLOUR unclippedColour;
  int x;
  int antialias_line = true;
  int skip_lines;
  int first_line;
  int skip_odd_lines;

  /* Set jitterscale. */

  JitterScale = opts.JitterScale / (DBL)opts.AntialiasDepth;

  /* Odd/even line tracing depends on the frame number. */

  skip_odd_lines = !(((opts.FrameSeq.FrameNumber % 2)==1) ^ opts.FrameSeq.Odd_Field_Flag);

  /* Field rendering starts on an odd or even line. */

  skip_lines = (opts.FrameSeq.Field_Render_Flag) && !(opts.Options & ANTIALIAS);

  /* Get first line number. */

  first_line = (opts.Options & ANTIALIAS)?opts.First_Line-1:opts.First_Line;

  /* Loop over all rows. */
//ROI
  for (Current_Line_Number = first_line; Current_Line_Number < opts.Last_Line; Current_Line_Number++)
  {
    /* Skip odd or even lines depending on the line number. */

    if ((skip_lines) && ((Current_Line_Number % 2) == skip_odd_lines))
    {    
      /* Write previous line again. */

      if (Current_Line_Number > opts.First_Line)
      {    
        output_single_image_line_with_alpha_correction(Previous_Line, Current_Line_Number);
      }    
      else 
      {    
        POV_WRITE_LINE (Previous_Line, Current_Line_Number)
      }    
           
      continue;
    }    

12) calculix
A. gprofile 결과 분석
nonlingeo 함수가 99.8%의 실행 시간을 차지한다. main 함수에 while 루프를 돈다. while 루프 이전에 sync를 맞추면 된다.
B. ROI

//CalculiX.c
nload=0;nforc=0;nboun=0;nk=0;nmpc=0;nflow=0;
nlabel=8;

for(k=0;k<3;++k){
  p1[k]=0.;
  p2[k]=0.;
  bodyf[k]=0.;
}
om=0.;
iamom=0;
iambodyf=0;
//ROI
while(istat>=0) {

13) GemsFDTD
A. gprofile 결과 분석
main 함수에서 leapfrog를 호출하며, leapfrog는 100%의 실행 시간을 차지한다. 내부에서 UPMLupdateE, UPMLupdateH, NFT_Store, updateE_homo, updateH_homo 등을 호출하는데, 이들이 상당 부분의 실행 시간을 차지한다. 따라서 while 루프 앞에서 sync를 맞추면 된다.
B. ROI

c leapfrog.f90 
! Only perform initialization. This is useful if a flop counter tool is used.
if (progress_awtwb) then                                             ! (ulfa)
  write(*,*) 'TERMINATING, because PROGRESS/Awtwb was set'
  stop
end if

!-------------- TIMESTEPPING -----------------
c ROI
do ts = 1,nts

  if (ts==1) then
    write(*,*) '============================================================'
    write(*,*) 'Entering timestepping loop'
    write(*,*) 'Total number of iterations are ', nts 
  end if

! Start timer. The first time step may differ from the others in performance,
! since it does not have any preceding time step. We do not want to pollute
! the timing by including it.
  if (ts==2) then                                    
    write(*,*) 'Starting timer in the beginning of the second time step'
!   !SPEC: no, don't; SPEC prefers to do its own timing jh/12/feb/04
!   !CALL timer(t_start,0.0_sfp)
  end if

  CALL updateH_homo(nx,ny,nz,Hx,Hy,Hz,Ex,Ey,Ez)

  if (OBC_Type==OBC_UPML) then
    CALL UPMLupdateH(nx,ny,nz,Hx,Hy,Hz,Ex,Ey,Ez)
  end if
  
  if (HuyPulsetype>0) then
    CALL HuygensH(ts,Hx,Hy,Hz)
  end if

14) tonto
A. gprofile 결과 분석
main이 전체 실행 시간의 99.7%, read_keywords가 99.7%, process_keyword가 99.7%를 차지한다. read_keywords 함수 내부에서 루프 이전에 sync를 맞추면 된다.
B. ROI

c mol_main.F90
   subroutine main(self)
    MOL :: self 
   ! Main molecule run-loop; assumes stdin and stdout have been defined.
      PTR :: self 
      STACK("MOL:main")
      START_TIMER("MOL:main")
      call set_error_output_file_(tonto,stdout)
      call create_(self)
      call put_banner_(self)
      call read_keywords_(self)   ! do it here
      call flush_(stdout)
      call text_(stdout,time_taken_(std_time,"job "//'"'// trim(self%name) //'"'))
      call text_(stdout,cpu_time_taken_(std_time,"job "//'"'// trim(self%name) //'"'))
      call destroy_(self)
     STOP_TIMER("MOL:main")
      CHECK
   end subroutine

   subroutine put_banner(self)
    MOL :: self 
   ! Put to stdout the current TONTO banner
     STACK("MOL:put_banner")
     START_TIMER("MOL:put_banner")
     call text_(stdout," ")
     call text_(stdout,"---------------------------------------------------------------")
     call text_(stdout,"                                                               ")
     call text_(stdout," T   O   N   T   O                                             ")
     call text_(stdout,"                                                               ")
     call text_(stdout," A free object-based system for computational chemistry        ")
     call text_(stdout,"                                                               ")
     call text_(stdout," Version 1.0                                                   ")
     #ifdef SPEC_CPU
     call text_(stdout," with minor modifications for SPEC                             ")
     #endif
     call text_(stdout,"                                                               ")
     call text_(stdout," For conditions of use, on-line documentation, and contributor ")
     call text_(stdout," and developer information see :-                              ")
     call text_(stdout,"                                                               ")
     call text_(stdout," www."//"theochem."//"uwa."//"edu."//"au/tonto/                ")
     call text_(stdout,"                                                               ")
     call text_(stdout," Dylan Jayatilaka                                              ")
     call text_(stdout," Daniel Grimwood                                               ")
     call text_(stdout,"---------------------------------------------------------------")
     call text_(stdout," ")
     call start_(std_time)
     call text_(stdout, start_time_(std_time) )
     STOP_TIMER("MOL:put_banner")
      CHECK
   end subroutine

   subroutine reset_molecule(self)
    MOL :: self 
   ! Resets the mol data type and reruns the read routine
      PTR :: self 
      STR(STR_SIZE) :: word 
      STACK("MOL:reset_molecule")
      START_TIMER("MOL:reset_molecule")
      call destroy_(self)
      call create_(self)
      call read_(stdin,word); call to_lower_case_(word)         ! First keyword must be "name"
      ENSURE(word=="name","MOL:reset_molecule ... first keyword must be name")
      call read_(stdin,self%name)
     STOP_TIMER("MOL:reset_molecule")
      UNSTACK
   end subroutine

   recursive subroutine read_keywords(self)
    MOL :: self 
   ! Read data from "stdin" using keyword style input.
   ! NOTE : this routine reuires a MOL pointer self variable
      PTR :: self 
      STR(STR_SIZE) :: word 
      STACK("MOL:read_keywords")
      START_TIMER("MOL:read_keywords")
      call read_(stdin,word)
      ENSURE(word=="{","MOL:read_keywords ... expecting an open bracket symbol, {")
c ROI
      read_loop: do          ! Loop over keywords
         call read_(stdin,word)
         if (word=="}")      exit read_loop
         if (reverted_(stdin)) exit read_loop
         call process_keyword_(self,word)
      end do read_loop
     STOP_TIMER("MOL:read_keywords")
      UNSTACK
   end subroutine

15) lbm
A. gprofile 결과 분석
LBM_performStreamCollide 함수가 실행 시간의 99.6%를 차지하며, 이는 main 함수에서 for 루프를 돌며 호출됨. 따라서 main 함수의 for 루프 앞에서 sync를 맞추면 된다.
B. ROI

//main.c
int main( int nArgs, char* arg[] ) { 
    MAIN_Param param;
#if !defined(SPEC_CPU)
    MAIN_Time time;
#endif
    int t;

    MAIN_parseCommandLine( nArgs, arg, &param );
    MAIN_printInfo( &param );
    MAIN_initialize( &param );
#if !defined(SPEC_CPU)
    MAIN_startClock( &time );
#endif
//ROI
    for( t = 1; t <= param.nTimeSteps; t++ ) { 
        if( param.simType == CHANNEL ) { 
            LBM_handleInOutFlow( *srcGrid );
        }   

        LBM_performStreamCollide( *srcGrid, *dstGrid );
        LBM_swapGrids( &srcGrid, &dstGrid );

        if( (t & 63) == 0 ) { 
            printf( "timestep: %i\n", t );
            LBM_showGridStatistics( *srcGrid );
        }   
    }   

16) wrf
A. gprofile 결과 분석
main 함수에서 integrate 함수를 호출하며, 이 함수는 전체 시간의 100%를 차지한다. integrate 함수를 호출하는 지점 바로 앞에서 sync한다.
B. ROI

c wrf.F90
!</DESCRIPTION>


   !  The forecast integration for the most coarse grid is now started.  The
   !  integration is from the first step (1) to the last step of the simulation.

   head_grid%start_subtime = head_grid%start_time
   head_grid%stop_subtime = head_grid%stop_time
   CALL       wrf_debug ( 100 , 'wrf: calling integrate' )
c ROI
   CALL integrate ( head_grid )
   CALL       wrf_debug ( 100 , 'wrf: back from integrate' )

17) sphinx3
A. gprofile 결과 분석
live_utt_decode_block 함수가 실행 시간의 99.9%를 차지하며, 이는 main 함수의 for 루프에서 반복적으로 호출된다. 따라서 main 함수의 for 루프 시작 직전에 sync해주면 된다.
B. ROI

//spec_main_live_pretend.c
        fflush(stdout); fclose(sfp);
        iutt++;
    }   
    nutt = iutt;

    // Now apply the beams to each of the utterances in turn
//ROI
    for (ib=0; ib<nbeams; ib++) {
        kb->beam->hmm    = logs3 (beams[ib][HMMBEAM]);
        kb->beam->ptrans = logs3 (beams[ib][PBEAM]);
        kb->beam->word   = logs3 (beams[ib][WBEAM]);
        kb->beam->subvq  = logs3 (beams[ib][SUBVQBEAM]);
        E_INFO("Beam= %d, PBeam= %d, WBeam= %d, SVQBeam= %d\n",
            kb->beam->hmm, kb->beam->ptrans, kb->beam->word, kb->beam->subvq);

        for (iutt=0; iutt<nutt; iutt++) {
            live_utt_set_uttid(uttid[iutt]);
            for (i=0;i<uttsize[iutt];i+=blksize){
                buflen = i+blksize < uttsize[iutt] ? blksize : uttsize[iutt]-i;
                endutt = i+blksize <= uttsize[iutt]-1 ? 0 : 1;
                nhypwds = live_utt_decode_block(
                           samps[iutt]+i,buflen,endutt,&parthyp);

                //SPEC:uncomment for useful diags E_INFO("PARTIAL HYP:");
                //if (nhypwds > 0)
                //    for (j=0; j < nhypwds; j++) fprintf(stderr," %s",parthyp[j].word);
                //fprintf(stderr,"\n");
            }   
        }   
    }  

3. SIGARCH ([MICRO’14] COMP: Compiler Optimizations for Manycore Processors)
최근 프로세서 제조사에서 computation offloading을 위해 manycore processor를 생산하고 있으나, 프로그래머들이 이를 적절하게 활용하지 못하고 있다. 이 논문에서는 manycore processor에서 offloading computation을 할 수 있도록 compiler optimization을 제안한다. 총 세 가지 원인이 performance bottleneck이 된다고 제시하며, 이에 대한 해결책을 제시한다. 1) Offloading을 위해서는 데이터 전송이 필요한데, 이 때 발생하는 데이터 전송 오버헤드가 상당하다. 이를 해결하기 위해 data streaming 기법을 제안한다. 2) 비규칙적인 메모리 접근은 캐시 지역성과 벡터화를 해친다. 따라서 메모리 접근을 정규화해 벡터화 가능하도록 한다. 3) 큰 데이터 구조에 대한 포인터 기반 접근이 효율성을 떨어뜨린다. 이를 해결하기 위해 새로운 메모리 메커니즘을 제안한다.
이 논문은 Xeon Phi 코프로세서를 대상으로 하고 있는데, 나는 Xeon Phi 코프로세서에 대해 알지 못해서 이해에 어려움을 겪었다. Xeon Phi 코프로세서는 코어가 60개로, 매우 병렬화된 프로그램을 실행하는 경우 성능 향상을 기대할 수 있다. 인텔에서 gpgpu에 대항하고자 만든 것이라고 함.


4. SPEC CPU 2006에 sync_all_processes 함수 삽입하기
여러 개의 SPEC CPU 2006 워크로드의 실행 시점을 맞추려면, 앞서 찾은 지점에 sync_all_processes() 함수를 호출해야 한다. 이 함수는 2015/03/25에 정의함.
1) C 프로그램에서 sync_all_processes() 함수 호출하기
– 해당 벤치마크의 디렉토리에 관련 파일 추가 (sem_helper.h, sync_all_processes.h)
– ROI가 있는 파일에서 include로 헤더 파일 추가
– sync_all_processes() 호출
2) Fortran 프로그램에서 sync_all_processes() 함수 호출하기
– 해결하지 못함.
– Makefile을 수정할 수 없는 것 같음. Manual을 읽어보니, 자동으로 생성된다고 함. 그리고 벤치마크라는 특성 상 config를 사용해서 빌드 옵션을 수정할 뿐, 직접 makefile을 수정하지는 않는다고 함.
– C의 sync_all_processes()를 호출하는 대신, Fortran에서 온전히 semaphore를 사용할 수도 있을 것. 하지만 예제가 부족하고, 있는 예제 또한 바로 쓸 수 있는 것 같지는 않음(Semaphores for fortran, stackoverflow, http://stackoverflow.com/questions/8564785/semaphores-for-fortran).

Advertisements
Posted in 1) Memo

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

누적 방문자 수
  • 98,779 hits
%d bloggers like this: