-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/timer/mpidtime.c
        -:    0:Graph:mpidtime.gcno
        -:    0:Data:mpidtime.gcda
        -:    0:Runs:771
        -:    0:Programs:204
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *  (C) 2001 by Argonne National Laboratory.
        -:    4: *      See COPYRIGHT in top-level directory.
        -:    5: */
        -:    6:
        -:    7:#include "mpiimpl.h"
        -:    8:
        -:    9:#if MPICH_TIMER_KIND == USE_GETHRTIME 
        -:   10:/* 
        -:   11: * MPID_Time_t is hrtime_t, which under Solaris is defined as a 64bit
        -:   12: * longlong_t .  However, the Solaris header files will define
        -:   13: * longlong_t as a structure in some circumstances, making arithmetic
        -:   14: * with hrtime_t invalid.  FIXME.  
        -:   15: * To fix this, we'll need to test hrtime_t arithmetic in the configure
        -:   16: * program, and if it fails, check for the Solaris defintions (
        -:   17: * union { double _d; int32_t _l[2]; }.  Alternately, we may decide that
        -:   18: * if hrtime_t is not supported, then neither is gethrtime.
        -:   19: *
        -:   20: * Note that the Solaris sys/types.h file *assumes* that no other compiler
        -:   21: * supports an 8 byte long long.  We can also cast hrtime_t to long long 
        -:   22: * if long long is available and 8 bytes.
        -:   23: */
        -:   24:void MPID_Wtime( MPID_Time_t *timeval )
        -:   25:{
        -:   26:    *timeval = gethrtime();
        -:   27:}
        -:   28:void MPID_Wtime_diff( MPID_Time_t *t1, MPID_Time_t *t2, double *diff )
        -:   29:{
        -:   30:    *diff = 1.0e-9 * (double)( *t2 - *t1 );
        -:   31:}
        -:   32:void MPID_Wtime_todouble( MPID_Time_t *t, double *val )
        -:   33:{
        -:   34:    *val = 1.0e-9 * (*t);
        -:   35:}
        -:   36:void MPID_Wtime_acc( MPID_Time_t *t1,MPID_Time_t *t2, MPID_Time_t *t3 )
        -:   37:{
        -:   38:    *t3 += ((*t2) - (*t1));
        -:   39:}
        -:   40:double MPID_Wtick( void )
        -:   41:{
        -:   42:    /* According to the documentation, ticks should be in nanoseconds.  This 
        -:   43:       is untested */ 
        -:   44:    return 1.0e-9;
        -:   45:}
        -:   46:
        -:   47:
        -:   48:#elif MPICH_TIMER_KIND == USE_CLOCK_GETTIME
        -:   49:void MPID_Wtime( MPID_Time_t *timeval )
        -:   50:{
        -:   51:    /* POSIX timer (14.2.1, page 311) */
        -:   52:    clock_gettime( CLOCK_REALTIME, timeval );
        -:   53:}
        -:   54:void MPID_Wtime_diff( MPID_Time_t *t1, MPID_Time_t *t2, double *diff )
        -:   55:{
        -:   56:    *diff = ((double) (t2->tv_sec - t1->tv_sec) + 
        -:   57:		1.0e-9 * (double) (t2->tv_nsec - t1->tv_nsec) );
        -:   58:}
        -:   59:void MPID_Wtime_todouble( MPID_Time_t *t, double *val )
        -:   60:{
        -:   61:    *val = ((double) t->tv_sec + 1.0e-9 * (double) t->tv_nsec );
        -:   62:}
        -:   63:void MPID_Wtime_acc( MPID_Time_t *t1, MPID_Time_t *t2, MPID_Time_t *t3 )
        -:   64:{
        -:   65:    int nsec, sec;
        -:   66:    
        -:   67:    nsec = t1->tv_nsec + t2->tv_nsec;
        -:   68:    sec  = t1->tv_sec + t2->tv_sec;
        -:   69:    if (nsec > 1.0e9) {
        -:   70:	nsec -= 1.0e9;
        -:   71:	sec++;
        -:   72:    }
        -:   73:    t3->tv_sec = sec;
        -:   74:    t3->tv_nsec = nsec;
        -:   75:}
        -:   76:
        -:   77:/* FIXME: We need to cleanup the use of the MPID_Generic_wtick prototype */
        -:   78:double MPID_Generic_wtick(void);
        -:   79:
        -:   80:double MPID_Wtick( void )
        -:   81:{
        -:   82:    struct timespec res;
        -:   83:    int rc;
        -:   84:
        -:   85:    rc = clock_getres( CLOCK_REALTIME, &res );
        -:   86:    if (!rc) 
        -:   87:	/* May return -1 for unimplemented ! */
        -:   88:	return res.tv_sec + 1.0e-9 * res.tv_nsec;
        -:   89:
        -:   90:    /* Sigh.  If not implemented (POSIX allows that), 
        -:   91:       then we need to use the generic tick routine */
        -:   92:    return MPID_Generic_wtick();
        -:   93:}
        -:   94:#define MPICH_NEEDS_GENERIC_WTICK
        -:   95:/* Rename the function so that we can access it */
        -:   96:#define MPID_Wtick MPID_Generic_wtick
        -:   97:
        -:   98:#elif MPICH_TIMER_KIND == USE_GETTIMEOFDAY
        -:   99:#ifdef HAVE_SYS_TIME_H
        -:  100:#include <sys/time.h>
        -:  101:#endif
        -:  102:#ifdef HAVE_UNISTD_H
        -:  103:#include <unistd.h>
        -:  104:#endif
        -:  105:void MPID_Wtime( MPID_Time_t *tval )
        -:  109:void MPID_Wtime_diff( MPID_Time_t *t1, MPID_Time_t *t2, double *diff )
      159:  110:{
      159:  111:    *diff = ((double) (t2->tv_sec - t1->tv_sec) + 
        -:  112:		.000001 * (double) (t2->tv_usec - t1->tv_usec) );
      159:  113:}
        -:  114:void MPID_Wtime_todouble( MPID_Time_t *t, double *val )
        -:  118:void MPID_Wtime_acc( MPID_Time_t *t1, MPID_Time_t *t2, MPID_Time_t *t3 )
    #####:  119:{
        -:  120:    int usec, sec;
        -:  121:    
    #####:  122:    usec = t2->tv_usec - t1->tv_usec;
    #####:  123:    sec  = t2->tv_sec - t1->tv_sec;
    #####:  124:    t3->tv_usec += usec;
    #####:  125:    t3->tv_sec += sec;
        -:  126:    /* Handle carry to the integer seconds field */
    #####:  127:    if (t3->tv_usec > 1.0e6) {
    #####:  128:	t3->tv_usec -= 1.0e6;
    #####:  129:	t3->tv_sec++;
        -:  130:    }
    #####:  131:}
        -:  132:#define MPICH_NEEDS_GENERIC_WTICK
        -:  133:
        -:  134:
        -:  135:#elif MPICH_TIMER_KIND == USE_LINUX86_CYCLE
        -:  136:#include <sys/time.h>
        -:  137:double MPID_Seconds_per_tick=0.0;
        -:  138:double MPID_Wtick(void)
        -:  139:{
        -:  140:    return MPID_Seconds_per_tick;
        -:  141:}
        -:  142:int MPID_Wtime_init(void)
        -:  143:{
        -:  144:    unsigned long long t1, t2;
        -:  145:    struct timeval tv1, tv2;
        -:  146:    double td1, td2;
        -:  147:
        -:  148:    gettimeofday(&tv1, NULL);
        -:  149:    MPID_Wtime(&t1);
        -:  150:    usleep(250000);
        -:  151:    gettimeofday(&tv2, NULL);
        -:  152:    MPID_Wtime(&t2);
        -:  153:
        -:  154:    td1 = tv1.tv_sec + tv1.tv_usec / 1000000.0;
        -:  155:    td2 = tv2.tv_sec + tv2.tv_usec / 1000000.0;
        -:  156:
        -:  157:    MPID_Seconds_per_tick = (td2 - td1) / (double)(t2 - t1);
        -:  158:    return 0;
        -:  159:}
        -:  160:/* Time stamps created by a macro */
        -:  161:void MPID_Wtime_diff( MPID_Time_t *t1, MPID_Time_t *t2, double *diff )
        -:  162:{
        -:  163:    *diff = (double)( *t2 - *t1 ) * MPID_Seconds_per_tick;
        -:  164:}
        -:  165:void MPID_Wtime_todouble( MPID_Time_t *t, double *val )
        -:  166:{
        -:  167:    /* This returns the number of cycles as the "time".  This isn't correct
        -:  168:       for implementing MPI_Wtime, but it does allow us to insert cycle
        -:  169:       counters into test programs */
        -:  170:    *val = (double)*t * MPID_Seconds_per_tick;
        -:  171:}
        -:  172:void MPID_Wtime_acc( MPID_Time_t *t1,MPID_Time_t *t2, MPID_Time_t *t3 )
        -:  173:{
        -:  174:    *t3 += (*t2 - *t1);
        -:  175:}
        -:  176:
        -:  177:
        -:  178:
        -:  179:#elif MPICH_TIMER_KIND == USE_GCC_IA64_CYCLE
        -:  180:#include <sys/time.h>
        -:  181:double MPID_Seconds_per_tick = 0.0;
        -:  182:double MPID_Wtick(void)
        -:  183:{
        -:  184:    return MPID_Seconds_per_tick;
        -:  185:}
        -:  186:int MPID_Wtime_init(void)
        -:  187:{
        -:  188:    unsigned long long t1, t2;
        -:  189:    struct timeval tv1, tv2;
        -:  190:    double td1, td2;
        -:  191:
        -:  192:    gettimeofday(&tv1, NULL);
        -:  193:    MPID_Wtime(&t1);
        -:  194:    usleep(250000);
        -:  195:    gettimeofday(&tv2, NULL);
        -:  196:    MPID_Wtime(&t2);
        -:  197:
        -:  198:    td1 = tv1.tv_sec + tv1.tv_usec / 1000000.0;
        -:  199:    td2 = tv2.tv_sec + tv2.tv_usec / 1000000.0;
        -:  200:
        -:  201:    MPID_Seconds_per_tick = (td2 - td1) / (double)(t2 - t1);
        -:  202:    return 0;
        -:  203:}
        -:  204:/* Time stamps created by a macro */
        -:  205:void MPID_Wtime_diff( MPID_Time_t *t1, MPID_Time_t *t2, double *diff )
        -:  206:{
        -:  207:    *diff = (double)( *t2 - *t1 ) * MPID_Seconds_per_tick;
        -:  208:}
        -:  209:void MPID_Wtime_todouble( MPID_Time_t *t, double *val )
        -:  210:{
        -:  211:    /* This returns the number of cycles as the "time".  This isn't correct
        -:  212:       for implementing MPI_Wtime, but it does allow us to insert cycle
        -:  213:       counters into test programs */
        -:  214:    *val = (double)*t * MPID_Seconds_per_tick;
        -:  215:}
        -:  216:void MPID_Wtime_acc( MPID_Time_t *t1,MPID_Time_t *t2, MPID_Time_t *t3 )
        -:  217:{
        -:  218:    *t3 += (*t2 - *t1);
        -:  219:}
        -:  220:
        -:  221:#elif MPICH_TIMER_KIND == USE_LINUXALPHA_CYCLE
        -:  222:
        -:  223:#error "LinuxAlpha cycle counter not supported"
        -:  224:
        -:  225:#elif (MPICH_TIMER_KIND == USE_WIN86_CYCLE) || (MPICH_TIMER_KIND == USE_WIN64_CYCLE)
        -:  226:double MPID_Seconds_per_tick = 0.0;
        -:  227:double MPID_Wtick(void)
        -:  228:{
        -:  229:    return MPID_Seconds_per_tick;
        -:  230:}
        -:  231:void MPID_Wtime_todouble( MPID_Time_t *t, double *d)
        -:  232:{
        -:  233:    *d = (double)(__int64)*t * MPID_Seconds_per_tick;
        -:  234:}
        -:  235:void MPID_Wtime_diff( MPID_Time_t *t1, MPID_Time_t *t2, double *diff)
        -:  236:{
        -:  237:    *diff = (double)((__int64)( *t2 - *t1 )) * MPID_Seconds_per_tick;
        -:  238:}
        -:  239:int MPID_Wtime_init( void )
        -:  240:{
        -:  241:    MPID_Time_t t1, t2;
        -:  242:    DWORD s1, s2;
        -:  243:    double d;
        -:  244:    int i;
        -:  245:
        -:  246:    MPID_Wtime(&t1);
        -:  247:    MPID_Wtime(&t1);
        -:  248:
        -:  249:    /* time an interval using both timers */
        -:  250:    s1 = GetTickCount();
        -:  251:    MPID_Wtime(&t1);
        -:  252:    /*Sleep(250);*/ /* Sleep causes power saving cpu's to stop which stops the counter */
        -:  253:    while (GetTickCount() - s1 < 200)
        -:  254:    {
        -:  255:	for (i=2; i<1000; i++)
        -:  256:	    d = (double)i / (double)(i-1);
        -:  257:    }
        -:  258:    s2 = GetTickCount();
        -:  259:    MPID_Wtime(&t2);
        -:  260:
        -:  261:    /* calculate the frequency of the assembly cycle counter */
        -:  262:    MPID_Seconds_per_tick = ((double)(s2 - s1) / 1000.0) / (double)((__int64)(t2 - t1));
        -:  263:    /*
        -:  264:    printf("t2-t1 %10d\nsystime diff %d\nfrequency %g\n CPU MHz %g\n", 
        -:  265:	(int)(t2-t1), (int)(s2 - s1), MPID_Seconds_per_tick, MPID_Seconds_per_tick * 1.0e6);
        -:  266:    */
        -:  267:    return 0;
        -:  268:}
        -:  269:/*
        -:  270:void TIMER_INIT()
        -:  271:{
        -:  272:    TIMER_TYPE t1, t2;
        -:  273:    FILETIME ft1, ft2;
        -:  274:    SYSTEMTIME st1, st2;
        -:  275:    ULARGE_INTEGER u1, u2;
        -:  276:
        -:  277:    t1 = 5;
        -:  278:    t2 = 5;
        -:  279:
        -:  280:    GET_TIME(&t1);
        -:  281:    GET_TIME(&t1);
        -:  282:
        -:  283:    GetSystemTime(&st1);
        -:  284:    GET_TIME(&t1);
        -:  285:    Sleep(500);
        -:  286:    GetSystemTime(&st2);
        -:  287:    GET_TIME(&t2);
        -:  288:
        -:  289:    SystemTimeToFileTime(&st1, &ft1);
        -:  290:    SystemTimeToFileTime(&st2, &ft2);
        -:  291:
        -:  292:    u1.QuadPart = ft1.dwHighDateTime;
        -:  293:    u1.QuadPart = u1.QuadPart << 32;
        -:  294:    u1.QuadPart |= ft1.dwLowDateTime;
        -:  295:    u2.QuadPart = ft2.dwHighDateTime;
        -:  296:    u2.QuadPart = u2.QuadPart << 32;
        -:  297:    u2.QuadPart |= ft2.dwLowDateTime;
        -:  298:
        -:  299:    MPID_Seconds_per_tick = (1e-7 * (double)((__int64)(u2.QuadPart - u1.QuadPart))) / (double)((__int64)(t2 - t1));
        -:  300:    printf("t2   %10d\nt1   %10d\ndiff %10d\nsystime diff %d\nfrequency %g\n CPU MHz %g\n", 
        -:  301:	(int)t2, (int)t1, (int)(t2-t1), (int)(u2.QuadPart - u1.QuadPart), MPID_Seconds_per_tick, MPID_Seconds_per_tick * 1.0e6);
        -:  302:    printf("t2-t1 %10d\nsystime diff %d\nfrequency %g\n CPU MHz %g\n", 
        -:  303:	(int)(t2-t1), (int)(u2.QuadPart - u1.QuadPart), MPID_Seconds_per_tick, MPID_Seconds_per_tick * 1.0e6);
        -:  304:}
        -:  305:*/
        -:  306:
        -:  307:
        -:  308:
        -:  309:#elif MPICH_TIMER_KIND == USE_QUERYPERFORMANCECOUNTER
        -:  310:double MPID_Seconds_per_tick=0.0;  /* High performance counter frequency */
        -:  311:int MPID_Wtime_init(void)
        -:  312:{
        -:  313:    LARGE_INTEGER n;
        -:  314:    QueryPerformanceFrequency(&n);
        -:  315:    MPID_Seconds_per_tick = 1.0 / (double)n.QuadPart;
        -:  316:    return 0;
        -:  317:}
        -:  318:double MPID_Wtick(void)
        -:  319:{
        -:  320:    return MPID_Seconds_per_tick;
        -:  321:}
        -:  322:void MPID_Wtime_todouble( MPID_Time_t *t, double *val )
        -:  323:{
        -:  324:    *val = (double)t->QuadPart * MPID_Seconds_per_tick;
        -:  325:}
        -:  326:void MPID_Wtime_diff( MPID_Time_t *t1, MPID_Time_t *t2, double *diff )
        -:  327:{
        -:  328:    LARGE_INTEGER n;
        -:  329:    n.QuadPart = t2->QuadPart - t1->QuadPart;
        -:  330:    *diff = (double)n.QuadPart * MPID_Seconds_per_tick;
        -:  331:}
        -:  332:void MPID_Wtime_acc( MPID_Time_t *t1, MPID_Time_t *t2, MPID_Time_t *t3 )
        -:  333:{
        -:  334:    t3->QuadPart += ((t2->QuadPart) - (t1->QuadPart));
        -:  335:}
        -:  336:
        -:  337:
        -:  338:
        -:  339:#endif
        -:  340:
        -:  341:#ifdef MPICH_NEEDS_GENERIC_WTICK
        -:  342:/*
        -:  343: * For timers that do not have defined resolutions, compute the resolution
        -:  344: * by sampling the clock itself.
        -:  345: *
        -:  346: * Note that this uses a thread-safe initialization procedure in the
        -:  347: * event that multiple threads invoke this routine
        -:  348: */
        -:  349:#undef FUNCNAME
        -:  350:#define FUNCNAME MPID_Wtick
        -:  351:#undef FCNAME
        -:  352:#define FCNAME MPIDI_QUOTE(FUNCNAME)
        -:  353:double MPID_Wtick( void )
       85:  354:{
        -:  355:    MPIU_THREADSAFE_INIT_DECL(initTick);
        -:  356:    static double tickval = -1.0;
        -:  357:    double timediff;
        -:  358:    MPID_Time_t t1, t2;
        -:  359:    int    cnt;
        -:  360:    int    icnt;
        -:  361:
       85:  362:    if (initTick) {
        8:  363:	MPIU_THREADSAFE_INIT_BLOCK_BEGIN(initTick);
        8:  364:	tickval = 1.0e6;
       88:  365:	for (icnt=0; icnt<10; icnt++) {
       80:  366:	    cnt = 1000;
       80:  367:	    MPID_Wtime( &t1 );
      231:  368:	    while (cnt--) {
      151:  369:		MPID_Wtime( &t2 );
      151:  370:		MPID_Wtime_diff( &t1, &t2, &timediff );
      151:  371:		if (timediff > 0) break;
        -:  372:		}
       80:  373:	    if (cnt && timediff > 0.0 && timediff < tickval) {
        8:  374:		MPID_Wtime_diff( &t1, &t2, &tickval );
        -:  375:	    }
        -:  376:	}
        8:  377:	MPIU_THREADSAFE_INIT_CLEAR(initTick);
        -:  378:	MPIU_THREADSAFE_INIT_BLOCK_END(initTick);
        -:  379:    }
       85:  380:    return tickval;
        -:  381:}
        -:  382:#endif