blob: ebfa5e8aa9e1daa8412fe6a300b53994792b7055 [file] [log] [blame] [edit]
/*****************************************************************************\
* Consume CPU and I/O resources.
*
* Copyright (C) 2013 Bull S. A. S.
* Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois.
* Written by Rod Schultz <rod.schultz@bull.com>
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>
#define SECOND2RUN 180
#define BURNBUFSIZ 1024*1024
#define CPUBUSY_PCT 40
#define READLOOP 10
#define WRITELOOP 20
// WRITELOOP must be greater than READLOOP
int busyloop(int burn, int nxny, double *m1, double *m2, double *m1m2)
{
int i, j, k;
int iters = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
int loopstart = tv.tv_usec;
int curtime = tv.tv_usec;
int busy = 0;
int nxny_x, ioff, joff;
while (busy < burn) {
iters++;
nxny_x = 0;
for (i=0; i<nxny; i++) {
ioff=i*nxny;
for (j=0; j<nxny; j++) {
joff=j*nxny;
m1m2[nxny_x]=0;
for (k=0; k<nxny; k++) {
m1m2[nxny_x] += m1[ioff+k]*m2[k+joff];
}
nxny_x++;
}
}
gettimeofday(&tv, NULL);
curtime = tv.tv_usec;
if (curtime < loopstart)
curtime += 1000000; // second rollover
busy = (curtime-loopstart);
}
return busy;
}
void do_io(char *burnpath, char *burnbuf, int iosize, int nread, int nwrite)
{
int ix;
FILE *fd = NULL;
fd = fopen (burnpath, "w");
if (!fd) {
perror ("fopen for write");
}
for (ix=0; ix<nwrite; ix++) {
if (!fwrite (burnbuf, iosize, 1, fd)) {
perror ("fwrite");
}
}
fclose(fd);
fd = fopen (burnpath, "r");
if (!fd) {
perror ("fopen for read");
}
for (ix=0; ix<nread; ix++) {
if (!fread (burnbuf, iosize, 1, fd)) {
perror ("fread");
}
}
fclose(fd);
}
int main (int argc, char **argv)
{
int nxny = 100; // Dimension of matrices
int writes = 0, reads = 0;
int actualbusy = 0, desiredbusy = 0;
int job_id, step_id, task_id;
int dobusy, loopstart, curtime, ms_busy, nap, irx, i,j;
double *m1, *m2, *m1m2;
float realpctbusy;
char *env_str, *burnbuf;
char burnpath[64];
struct timeval tv;
if (READLOOP > WRITELOOP) {
printf("\nFATAL: Compile parameter READLOOP > WRITELOOP");
exit(1);
}
if ((env_str = getenv("SLURM_JOB_ID")) == NULL) {
fprintf(stderr, "info: getenv(SLURM_JOB_ID) failed. "
"(Not running SLURM?)\n");
} else {
job_id = atoi(env_str);
if ((env_str = getenv("SLURM_STEPID")) != NULL) {
step_id = atoi(env_str);
}
if ((env_str = getenv("SLURM_PROCID")) != NULL) {
task_id = atoi(env_str);
}
}
burnbuf = malloc(sizeof(char)*BURNBUFSIZ);
memset(burnbuf,'\0',BURNBUFSIZ);
sprintf(burnpath,"/tmp/ioburn_%d_%d_%d",job_id,step_id,task_id);
ms_busy = CPUBUSY_PCT*10000;
m1 = malloc(sizeof(double)*nxny*nxny);
m2 = malloc(sizeof(double)*nxny*nxny);
m1m2 = malloc(sizeof(double)*nxny*nxny);
for (i=0; i<nxny; i++) {
for (j=0;j<nxny;j++) {
m1[i*nxny+j]= ((double) random());
m2[i*nxny+j]= ((double) random());
}
}
// 1 second load (%busy, io burn, sleep)
for (irx=0; irx<SECOND2RUN; irx++) {
gettimeofday(&tv, NULL);
desiredbusy += ms_busy;
loopstart = tv.tv_usec;
dobusy = desiredbusy - actualbusy;
if (dobusy > 0)
actualbusy += busyloop(dobusy, nxny, m1, m2, m1m2);
do_io(burnpath, burnbuf, BURNBUFSIZ, READLOOP, WRITELOOP);
reads += READLOOP;
writes += WRITELOOP;
gettimeofday(&tv, NULL);
curtime = tv.tv_usec;
if (curtime < loopstart)
curtime += 1000000;
nap = 1000000 - (curtime - loopstart);
usleep(nap);
}
realpctbusy = ((float) actualbusy)*100.0/((float)(SECOND2RUN*1000000));
printf("\ntest12.6.prog finished after %d seconds. busy=%3.1f%% "
"Reads=%d Writes=%d SLURM_JobId=%d StepId=%d TaskId=%d\n",
SECOND2RUN,realpctbusy,reads, writes,job_id,step_id,task_id);
free(m1);
free(m2);
free(m1m2);
free(burnbuf);
remove(burnpath);
return 0;
}