SPEC CPU 2006 ROI

2015/03/26, 2015/03/27 이틀에 걸쳐 SPEC CPU 2006의 ROI를 찾아봄. ROI라기보다는 각 벤치마크의 메인 루프에 가깝다. 하지만 코드 레벨에서는 다양한 상태 변화를 관찰할 수 없으므로, 코드 레벨에서는 이것이 최선인 것 같다.

Integer Benchmarks

1) perlbench
A. gprofile 결과 분석
수많은 함수들이 하나의 큰 cycle을 이루고 있으며, 이 cycle이 전체 실행 시간의 98.2%를 차지한다(S_regmatch, Perl_runops_standard…). 그 다음으로 perl_run이 실행 시간의 95.6%를 차지한다. perl_run이 주요 실행 부분인 것 같음. 하지만 perl_run 함수 내부를 정확히 이해하지는 못함. perl_run 함수 내부에서 ROI를 잡으면 될 것 같다.
B. ROI

//perl.c
int
perl_run(pTHXx)
{
    I32 oldscope;
    int ret = 0; 
    dJMPENV;
#ifdef USE_5005THREADS
    dTHX;
#endif

    oldscope = PL_scopestack_ix;
#ifdef VMS
    VMSISH_HUSHED = 0; 
#endif
//ROI
#ifdef PERL_FLEXIBLE_EXCEPTIONS
 redo_body:
    CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_vrun_body), oldscope);

2) bzip2
A. gprofile 결과 분석
compressStream, default_bzalloc, BZ2_bzWrite, BZ2_bzCompress, BZ2_compressBlock이 60~69% 정도의 실행시간을 차지한다. 결국 가장 핵심이 되는 함수는 compressStream이다. compressStream 함수는 spec_compress라는 이름으로 메인 함수에서 반복적으로 호출된다. 루프의 앞에서 sync를 맞춘다.
B. ROI

//spec.c
    /* Save off one byte every ~1k for validation */
    for (i = 0; i*VALIDATE_SKIP < input_size*MB; i++) {
    validate_array[i] = spec_fd[0].buf[i*VALIDATE_SKIP];
    }   


#ifdef DEBUG_DUMP
    fd = open ("out.uncompressed", O_RDWR|O_CREAT, 0644);
    write(fd, spec_fd[0].buf, spec_fd[0].len);
    close(fd);
#endif

    spec_initbufs();
//ROI
    for (level=5; level <= 9; level += 2) {
    debug_time();
    debug1(2, "Compressing Input Data, level %d\n", level);

    spec_compress(0,1, level);

    debug_time();
    debug1(3, "Compressed data %d bytes in length\n", spec_fd[1].len);

#ifdef DEBUG_DUMP
    {   
        char buf[256];
        sprintf(buf, "out.compress.%d", level);
        fd = open (buf, O_RDWR|O_CREAT, 0644);
        write(fd, spec_fd[1].buf, spec_fd[1].len);
        close(fd);
    }   
#endif

    spec_reset(0);
    spec_rewind(1);

3) gcc
A. gprofile 결과 분석
여러 개의 함수가 하나의 cycle을 이루며, 이것이 전체 실행 시간의 99.6% 차지함. 그 다음으로 toplev_main 함수가 99.3%의 실행 시간을 차지함. yyparse_1이 96.5%의 실행 시간을 차지함. 따라서 yyparse_1 함수가 ROI가 됨. main에서 toplev_main 호출, toplev_main에서 do_compile 호출, do_compile에서 compile_file 호출, compile_file에서 yyparse 호출.
B. ROI

//toplev.c
static void
compile_file ()                
{ 
  tree globals;                
  
  /* Initialize yet another pass.  */
  
  init_final (main_input_filename);
  init_branch_prob (dump_base_name);
  
  timevar_push (TV_PARSE);     
  
//ROI
  /* Call the parser, which parses the entire file
     (calling rest_of_compilation for each function).  */
  yyparse ();                  
  
  /* In case there were missing block closers,
     get us back to the global binding level.  */
  (*lang_hooks.clear_binding_stack) ();
  
  /* Compilation is now finished except for writing
     what's left of the symbol table output.  */
  
  timevar_pop (TV_PARSE);      
  
  if (flag_syntax_only)        
    return;                    

4) mcf
A. gprofile 결과 분석
global_opt가 실행 시간의 99.5% 차지함. global_opt가 호출하는 primal_net_simplex가 실행 시간의 82.4% 차지함. 따라서 global_opt 함수 내부에서 메인 루틴이 시작한다. global_opt 함수 내부에 while 루프가 있었고, 여기에서 문제를 받아 계속해서 처리하는 듯 하다. global_opt 내부가 ROI이다.
B. ROI

//mcf.c
#ifdef _PROTO_
long global_opt( void )
#else
long global_opt( )
#endif
{
    long new_arcs;
    long residual_nb_it;
    

    new_arcs = -1; 
    residual_nb_it = net.n_trips <= MAX_NB_TRIPS_FOR_SMALL_NET ?
        MAX_NB_ITERATIONS_SMALL_NET : MAX_NB_ITERATIONS_LARGE_NET;
//ROI
    while( new_arcs )
    {   
#ifdef REPORT
        printf( "active arcs                : %ld\n", net.m );
#endif

        primal_net_simplex( &net );

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를 찾아내기가 어렵지 않았다. 원래 hmmsearch.c만 수정했으나, 그렇게 하는 경우 다른 입력에 대해 sync 맞추지 못함. hmmcalibrate.c도 수정함.
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. */
//hmmcalibrate.c
  else if (num_threads > 0)
    printf("POSIX threads:            %d\n", num_threads);
  printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n");

  /***********************************************
   * Read the HMMs one at a time, and send them off
   * in probability form to one of the main loops.
   * The main loop functions are responsible for 
   * synthesizing random sequences and returning
   * a score histogram for each HMM.
   ***********************************************/

  nhmm = 0;
  mu     = MallocOrDie(sizeof(float) * mu_lumpsize);
  lambda = MallocOrDie(sizeof(float) * mu_lumpsize);

//ROI
  while (HMMFileRead(hmmfp, &hmm))
    {
      if (hmm == NULL)
    Die("HMM file may be corrupt or in incorrect format; parse failed");

      if (! do_pvm && num_threads == 0)
    main_loop_serial(hmm, seed, nsample, lenmean, lensd, fixedlen,
             &hist, &max);
#ifdef HMMER_PVM
      else if (do_pvm) {
    pvm_nslaves = 0;    /* solely to silence compiler warnings */
    main_loop_pvm(hmm, seed, nsample, pvm_lumpsize,
              lenmean, lensd, fixedlen,
              &hist, &max, &extrawatch, &pvm_nslaves);
      }

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번 호출). main 함수에서 for 루프를 돌며 encode_one_frame을 계속해서 호출함. 따라서 for 루프 앞에서 sync를 맞추면 됨.
B. ROI

//lencod.c
  // Write sequence header (with parameter sets)
  stats->bit_ctr_parametersets = 0;
  stats->bit_slice = start_sequence();
  stats->bit_ctr_parametersets += stats->bit_ctr_parametersets_n;
  start_frame_no_in_this_IGOP = 0;
//ROI
  for (img->number=0; img->number < input->no_frames; img->number++)
  {
    img->nal_reference_idc = 1;

    //much of this can go in init_frame() or init_field()?
    //poc for this frame or field
    img->toppoc = (input->intra_period && input->idr_enable ? IMG_NUMBER % input->intra_period : IMG_NUMBER) * (2*(input->jumpd+1));

    if ((input->PicInterlace==FRAME_CODING)&&(input->MbInterlace==FRAME_CODING))
      img->bottompoc = img->toppoc;     //progressive
    else
      img->bottompoc = img->toppoc+1;   //hard coded

    img->framepoc = min (img->toppoc, img->bottompoc);

    //frame_num for this frame
    //if (input->BRefPictures== 0 || input->successive_Bframe == 0 || img-> number < 2)
    if ((input->BRefPictures== 0 &&  input->PyramidCoding == 0) || input->successive_Bframe == 0 || img-> number < 2)// ||  input->PyramidCoding == 0)
      img->frame_num = (input->intra_period && input->idr_enable ? IMG_NUMBER % input->intra_period : IMG_NUMBER) % (1 << (log2_max_frame_num_minus4 + 4));
    else 

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 함수는 main에서 반복적으로 호출한다. while 루프 앞에서 sync를 맞춘다.
B. ROI

//control.c
int main( int argc, char **argv ){
    int meascount,traj_done;
    int prompt;
    int s_iters,avs_iters,avspect_iters,
        avbcorr_iters;
    double dtime, dclock();

    initialize_machine(argc,argv);
    g_sync();
    /* set up */
    prompt = setup();
//ROI
    /* loop over input sets */
    while( readin(prompt) == 0){ 

    /* perform warmup trajectories */
    dtime = -dclock();
    for( traj_done=0; traj_done < warms; traj_done++ ){
            update();
    }   
    node0_printf("WARMUPS COMPLETED\n"); fflush(stdout);

    /* perform measuring trajectories, reunitarizing and measuring  */
    meascount=0;        /* number of measurements       */
    avspect_iters = avs_iters = avbcorr_iters = 0;
    for( traj_done=0; traj_done < trajecs; traj_done++ ){  

        /* do the trajectories */
        s_iters=update();

        /* measure every "propinterval" trajectories */
        if( (traj_done%propinterval)==(propinterval-1) ){

4) zeusmp
A. gprofile 결과 분석
transprt 함수가 전체 실행 시간의 92.4%를 차지함. transprt 함수는 ct 함수를 150회 호출함. transprt 함수는 continue – goto로 이루어지는 루프 안에 있다. 따라서 이 앞에서 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
c ROI
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
        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를 호출한다. main 함수에서 runComputes를 RUN_AND_CHECKSUM으로 정의한다. 그리고 for 루프 안에서 반복적으로 호출한다. 따라서 RUN_AND_CHECKSUM을 반복적으로 호출하는 for 루프 앞에서 sync를 맞추면 된다.
B. ROI

//spec_namd.C
  FILE *output_file = 0;
  if ( output ) { 
    if ( output[0] == '-' ) { 
      printf("sending output to stdout\n");
      output_file = stdout;
    } else {
      output_file = fopen(output,"w");
      if ( ! output_file ) { 
        printf("unable to open output file\n");
        exit(-2);
      }   
      printf("writing to output file %s\n",output);
    }   
  }

//ROI
  for ( i = 0; i < iterations; ++i ) { 
    SET_MODE(1,0,0)
    RUN_AND_CHECKSUM
    WRITE(r100)
    SET_MODE(1,1,0)
    RUN_AND_CHECKSUM
    WRITE(r110)
    SET_MODE(1,1,1)
    RUN_AND_CHECKSUM
    WRITE(r111)
    SET_MODE(0,0,0)
    RUN_AND_CHECKSUM
    WRITE(r000)
    SET_MODE(0,1,0)
    RUN_AND_CHECKSUM
    WRITE(r010)
    SET_MODE(0,1,1)
    RUN_AND_CHECKSUM
    WRITE(r011)

    r100.compare(r110);
    r100.compare(r111);
    r100.compare(r000);
    r100.compare(r010);
    r100.compare(r011);

    r110.compare(r111);
    r110.compare(r000);
    r110.compare(r010);
    r110.compare(r011);

    r111.compare(r000);
    r111.compare(r010);
    r111.compare(r011);

    r000.compare(r010);
    r000.compare(r011);

    r010.compare(r011);

    patchList.moveatoms();

  }

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");
            }   
        }   
    }  
Advertisements
Tagged with: , , ,
Posted in 2) Computer Engineering
2 comments on “SPEC CPU 2006 ROI
  1. 최두헌 says:

    안녕하세요 질문 좀 해두 될까요!
    SPEC 2006 벤치 마크들에서, parsec의 fluidanimate 처럼 메모리 사용량이 많은 벤치마크가 혹시 있나요?
    ㅠㅠ

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

누적 방문자 수
  • 88,681 hits
%d bloggers like this: