/****************************************************** /* /* consume ratio freq /* to consume cpu time at ratio and frequency. /* The original code was from Peter Zijlstra, /* the kernal.org maintainer of the sched /* area of the kernel code. /* /* consume1.c Smythies 2014.07.05 /* Since fixed work packet calibration is /* based on the minimum pstate, fractions /* of over 100% are allowed. /* /* consume1.c Smythies 2014.06.27 /* As it turns out, my processor uses more /* energy for a fixed work packet at higher /* CPU clock rates. /* I get at least one overrun always the first /* time after a re-boot. Change it from a once /* only flag to a counter. /* Eliminate the floating point processor from /* fixed packet loop and get much better /* granularity for the calibration. /* /* consume1.c Smythies 2014.06.24 /* Attempt to make fixed work packet per period. /* The point is to finish faster for higher /* CPU clock rates, and to use less energy. /* /* consume.c Smythies 2014.06.07 /* Fix dense math issue with elapsed time. /* /* consume.c Smythies 2014.05.31 /* Even though I don't like the extra overhead, /* List its PID and some times to assist /* correlating with "perf record" data. /* /* consume.c Smythies 2014.05.05 /* Fix usage message. /* /* consume.c Smythies 2013.11.04 /* Add a time to execute parameter. /* allow the fraction to be as low as 0.5 percent /* /* consume.c Smythies 2012.06.27 /* More precision desired. Switch to doubles for /* run time parameters. /* /* consume.c Smythies 2012.06.23 /* I think in frequency for this stuff, so change /* the run time parameter from period to frequency. /* Make it not optional. /* /* consume.c Smythies 2012.06.23 /* First just try to compile the code as sent /* from Peter Zijlstra. /* But converted to my coding standards (which will /* annoy Peter if it ever gets sent back). /* /******************************************************/ // for the fixed work packet stuff, calibration for your // processor is required. // lock your processor at the minimum pstate and then // set this number as large as possible witrhout overruns // at a low sleep / load rate. // Of course, the calibration might need to checked // as the compiler or kernel evolves. // For intel Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz #define CALIBRATION 151 #include #include #include #include #include unsigned long long stamp(void){ struct timeval tv; gettimeofday(&tv, NULL); return (unsigned long long)tv.tv_sec * 1000000 + tv.tv_usec; } /* endprocedure */ void consume(int spin, int total, int elapsed){ unsigned long long begin, now, start, lelapsed; int i, j, k; // double x, y, z; int overruns; overruns = 0; begin = stamp(); start = begin; now = begin; lelapsed = (unsigned long long)elapsed * (unsigned long long) 1000000; while((long long)(now - start) < lelapsed) { /* for the requested time */ // for(i = 0; i < spin; i++){ /* do a fixed packet of work */ // for(j = 0; j < 8; j++){ // z = (double)(i + j) / 25.0; // x = sin(z); // y = sqrt(fabs(x)); // z = z + y; /* prevent the optimizer from taking out the loop */ // } /* endfor */ // } /* endfor */ for(i = 0; i < spin; i++){ /* do a fixed packet of work */ for(j = 0; j < CALIBRATION; j++){ k = (i + j) / 25; k = k + i + j; } /* endfor */ } /* endfor */ now = stamp(); if ((long long)(now - begin) < total ) { usleep(total - (now - begin)); } else { overruns++; // printf("\n Overrun: %llu %d\n", now - begin, total); } /* endif */ begin += total; now = stamp(); } /* endwhile */ printf(" Elapsed: %llu Now: %llu Overruns: %d\n", (now - start), now, overruns); } /* endprocedure */ int main(int argc, char **argv){ double frac, freq, duration, period; printf("consume: %s %s %s PID: %d", argv[1], argv[2], argv[3], getpid()); switch(argc){ case 4: frac = atof(argv[1]); freq = atof(argv[2]); duration = atof(argv[3]); break; default: fprintf(stderr, "%s \n frac -- [0.5-100.0] %% of time to burn\n freq -- [hz] (min 1.0) frequency of burn/sleep cycle\n duration -- [seconds] (0.0 means 1 day) time for program to run\n", argv[0]); return -1; } /* endcase */ /* printf("consume: %lf %lf %lf\n", frac, freq, duration); /* */ // if (frac > 100.0){ // frac = 100.0; // } /* endif */ if (frac < 0.50){ frac = 0.50; } /* endif */ if (freq < 1.0){ freq = 1.0; } /* endif */ if (duration <= 0.0){ duration = 86400.0; } /* endif */ period = 1000000.0 / freq; /* printf("consume: %lf %lf %lf %lf\n", frac, freq, period, duration); /* */ consume((int)(period * frac / 100.0 + 0.5), (int)(period + 0.5), (int)(duration + 0.5)); return 0; } /* endprocedure */