Как рассчитать время выполнения в C? - PullRequest
0 голосов
/ 06 октября 2011

Как рассчитать время выполнения в следующем коде:

#include <stdio.h>  /* Core input/output operations                         */
#include <stdlib.h> /* Conversions, random numbers, memory allocation, etc. */
#include <math.h>   /* Common mathematical functions                        */
#include <time.h>   /* Converting between various date/time formats         */
#include <sys/time.h>
#define PI      3.1415926535   /* Known vaue of PI                          */
#define NDARTS     128   /* Number of darts thrown                    */
double pseudo_random(double a, double b) {
double r;  /* Random number */
r = ((b - a) * ((double) rand()/(double) RAND_MAX)) + a;
 return r;
}
int main (int argc, char *argv[]) {
int    n_procs,       /* Number of processors                 */
llimit,        /* Lower limit for random numbers       */
ulimit,        /* Upper limit for random numbers       */
n_circle,      /* Number of darts that hit the circle  */
i;             /* Dummy/Running index                  */
double pi_sum,        /* Sum of PI values from each WORKER    */
x,             /* x coordinate, betwen -1 & +1         */
y,             /* y coordinate, betwen -1 & +1         */
z,             /* Sum of x^2 and y^2                   */
error;         /* Error in calculation of PI           */
clock_t start_time,    /* Wall clock - start time              */
end_time;      /* Wall clock - end time                */
struct timeval stime, starttime1, endtime1;
struct timeval tv1, tv2, diff;

llimit   = -1;
ulimit   = 1;
n_circle = 0;
printf("\n  Monte Carlo method of finding PI\n\n");
printf("    Number of processors : %d\n", n_procs);
printf("    Number of darts      : %d\n\n", NDARTS);
gettimeofday(&tv1, NULL);
gettimeofday(&stime, NULL);
srand(stime.tv_usec * stime.tv_usec * stime.tv_usec * stime.tv_usec);
for (i = 1; i <= NDARTS; i++) {
x = pseudo_random(llimit, ulimit);
y = pseudo_random(llimit, ulimit);
z = pow(x, 2) + pow(y, 2);
if (z <= 1.0) {
   n_circle++;
  }
}


pi_sum = 4.0 * (double)n_circle/(double)NDARTS;
pi_sum = pi_sum / n_procs;
error = fabs((pi_sum - PI)/PI) * 100;
gettimeofday(&tv2, NULL);
double timeval_subtract (result, x, y)
{
result = ((double)  x - (double) y ) / (double)CLOCKS_PER_SEC;
}
double result1 = timeval_subtract(&diff, &tv1, &tv2);
printf("    Known value of  PI   : %11.10f\n", PI);
printf("    Average value of PI  : %11.10f\n", pi_sum);
printf("    Percentage Error     : %10.8f\n", error);
printf("    Time   : \n", clock() );
printf("    Start Time   : \n",&tv1);
printf("    End Time   :\n", &tv2);
printf("    Time elapsed (sec)   : \n", result1 );
 return 0;
} 

Я использовал функцию timeval_subtract, и когда я выполняю код, я получил:

Monte Carlo method of finding PI

Number of processors : 16372
Number of darts      : 128

Known value of  PI   : 3.1415926535
Average value of PI  : 0.0002004184
Percentage Error     : 99.99362048
Time   : 
Start Time   : 
End Time   :
Time elapsed (sec)   :

Сначала яне смог найти ошибку в определении количества процессоров (мне нужно получить 1 процессор)прошло пусто?

Ответы [ 4 ]

1 голос
/ 06 октября 2011

n_procs никогда не инициализируется, значение 16372, которое выводится на печать, просто соответствует тому, которое было ранее в стеке.

Стандартная библиотека C не предоставляет функциональных возможностей для подсчета числа процессоров или высокопроизводительных таймеров., так что вам придется взглянуть на другие способы запроса этого.Например, POSIX и Windows API предоставляют такую ​​функциональность.

edit: См. Программно найдите количество ядер на машине , чтобы узнать, как инициализировать n_procs.Видя, как вы используете gettimeofday, вы, вероятно, на какой-то Unix-вариант;"n_procs = sysconf (_SC_NPROCESSORS_ONLN);"это, вероятно, то, что вы хотите.

1 голос
/ 06 октября 2011

Попробуйте это:

printf("    Time   : %lu\n", clock() );
printf("    Start Time   : %lds %ldus\n", tv1.tv_sec, tv1.tv_usec);
printf("    End Time   : %lds %ldus\n", tv2.tv_sec, tv2.tv_usec);

И для:

double timeval_subtract (result, x, y)

используйте следующее, чтобы вернуть разницу во времени в микросекундах:

long timeval_subtract (struct timeval * result, struct timeval * x, struct timeval * y)
{
   long usec = x->tv_sec * 1000000L + x->tv_usec;
   usec -= (y->tv_sec * 1000000L + y->tv_usec);

   result->tv_sec = usec / 1000000L;
   result->tv_usec = usec % 1000000L;

   return usec;
}

В зависимости отразница двух дат x и y, возвращаемое значение функции timeval_subtract (не значение, представленное result!) может быть неправильным из-за переполнения.

Предполагается, чтоlong имеет ширину 32 бита, это переполнение будет происходить с различием, превышающим 4294 с, для long с 64 битами (что должно быть в случае с 64-битными машинами) переполнение произойдет намного позже ...; -)

1 голос
/ 06 октября 2011

Поскольку у вас нет подходящих форматных строк для них, вам нужно что-то, начинающееся с '%', например:

printf("    Time   :%d \n", clock() );
0 голосов
/ 06 октября 2011

Я бы попробовал следующее:

int     timeval_subtract ( struct timeval *result, struct timeval *x, struct timeval *y ) {

    if ( x->tv_usec < y->tv_usec ) {
            int nsec = ( y->tv_usec - x->tv_usec ) / 1000000 + 1;
            y->tv_usec -= 1000000 * nsec;
            y->tv_sec += nsec;
    }
    if (x->tv_usec - y->tv_usec > 1000000) {
            int nsec = ( x->tv_usec - y->tv_usec ) / 1000000;
            y->tv_usec += 1000000 * nsec;
            y->tv_sec -= nsec;
    }

    result->tv_sec = x->tv_sec - y->tv_sec;
    result->tv_usec = x->tv_usec - y->tv_usec;

    return x->tv_sec < y->tv_sec;
}

void Start ( struct timeval *timer_profiling ) {
        if ( timer_profiling == NULL )   return;
        gettimeofday ( timer_profiling , NULL );
        return;
}

void End ( struct timeval *timer_profiling , char *msg ) {
        struct timeval res;
        struct timeval now;
        gettimeofday ( &now , NULL );

        if ( msg == NULL )      return;

        timeval_subtract ( &res , &now , timer_profiling );
        sprintf ( msg , "[ %ld,%.3ld ms]" , res.tv_sec*1000 + (long)round(res.tv_usec/1000) , res.tv_usec - (long)round(res.tv_usec/1000)*1000);

        return;
}

Запустить (& s) один с выделенным параметром timer_profiling, затем извлечь результат в строку, вызвав End (& s, buff);

...