diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2020-10-18 00:24:06 -0400 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2020-10-18 00:24:06 -0400 |
| commit | 41358857592f1908d0c0f9898b6c9acabc1ad161 (patch) | |
| tree | 3ca3bf4ce9c5a2b34eaa991dc73a2e055c67e3e4 /baseline/source | |
| parent | e5db76ee18640ce27df8756e573ef8b497af4750 (diff) | |
Rewrite extra.h for task baselines to be easier to use
New macro `for_each_job` simplifies instrumentation.
Backwards-compatible.
Diffstat (limited to 'baseline/source')
| -rw-r--r-- | baseline/source/extra.h | 275 |
1 files changed, 163 insertions, 112 deletions
diff --git a/baseline/source/extra.h b/baseline/source/extra.h index 02e97af..e8f3d18 100644 --- a/baseline/source/extra.h +++ b/baseline/source/extra.h | |||
| @@ -53,45 +53,60 @@ extern int sched_getcpu(); | |||
| 53 | #define LOAD_PARAMS LOAD_PARAMS_ITRL | 53 | #define LOAD_PARAMS LOAD_PARAMS_ITRL |
| 54 | #endif | 54 | #endif |
| 55 | 55 | ||
| 56 | // Store state globally so that the job can be outside main() | ||
| 57 | // Arrays use float as a comprimise between overflow and size | ||
| 58 | float *_rt_exec_time; | ||
| 59 | #if MMDC_PERF | ||
| 60 | float *_rt_mmdc_read; | ||
| 61 | float *_rt_mmdc_write; | ||
| 62 | #endif | ||
| 63 | long _rt_jobs_complete; | ||
| 64 | long _rt_max_jobs; | ||
| 65 | int _rt_core; | ||
| 66 | int _rt_will_output; | ||
| 67 | struct timespec _rt_start, _rt_end; | ||
| 68 | |||
| 69 | char *_rt_run_id; | ||
| 70 | char *_rt_our_prog_name; | ||
| 71 | #define _RT_FILENAME_LEN 64 | ||
| 72 | |||
| 56 | #define LOAD_PARAMS_ITRL \ | 73 | #define LOAD_PARAMS_ITRL \ |
| 57 | if (argc != 6) { \ | 74 | if (argc != 6) { \ |
| 58 | fprintf(stderr, "Usage: %s <name> <loops> <my core> <runID> <save results?>\n", argv[0]);\ | 75 | fprintf(stderr, "Usage: %s <name> <loops> <my core> <runID> <save results?>\n", argv[0]);\ |
| 59 | fprintf(stderr, " <loops> integer number of iterations. -1 for infitite.\n");\ | 76 | fprintf(stderr, " <loops> integer number of iterations. -1 for infitite.\n");\ |
| 60 | fprintf(stderr, " <save results?> 1 to save results, 0 to discard.\n");\ | 77 | fprintf(stderr, " <save results?> 1 to save results, 0 to discard.\n");\ |
| 78 | fprintf(stderr, " <my core> UNUSED. Core is now auto-detected.\n");\ | ||
| 79 | exit(1);\ | ||
| 80 | }\ | ||
| 81 | _rt_our_prog_name = argv[1];\ | ||
| 82 | _rt_max_jobs = atol(argv[2]);\ | ||
| 83 | _rt_core = sched_getcpu();\ | ||
| 84 | _rt_run_id = argv[4];\ | ||
| 85 | _rt_will_output = atoi(argv[5]);\ | ||
| 86 | if (_rt_max_jobs < 0 && _rt_will_output != 0) {\ | ||
| 87 | fprintf(stderr, "Infinite loops only supported when _rt_will_output is disabled!\n");\ | ||
| 61 | exit(1);\ | 88 | exit(1);\ |
| 62 | }\ | 89 | }\ |
| 63 | char *thisProgram=argv[1];\ | 90 | if (strlen(_rt_run_id) + 5 > _RT_FILENAME_LEN) {\ |
| 64 | int parsedMaxJobs=atoi(argv[2]);\ | 91 | fprintf(stderr, "Run ID is too large! Keep it to less than %d characters.\n", _RT_FILENAME_LEN);\ |
| 65 | unsigned int thisCore=atoi(argv[3]);\ | ||
| 66 | thisCore = sched_getcpu();\ | ||
| 67 | char *runID=argv[4];\ | ||
| 68 | int output=atoi(argv[5]);\ | ||
| 69 | if (parsedMaxJobs < 0 && output != 0){\ | ||
| 70 | fprintf(stderr, "Infinite loops only supported when output is disabled!\n");\ | ||
| 71 | exit(1);\ | 92 | exit(1);\ |
| 72 | }\ | 93 | }\ |
| 73 | /* Cheat. -1 is larger than jobsComplete can ever reach. */\ | 94 | _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\ |
| 74 | unsigned int maxJobs = parsedMaxJobs;\ | 95 | if (!_rt_exec_time) {\ |
| 75 | struct timespec _start, _end;\ | 96 | perror("Unable to allocate buffer for execution times");\ |
| 76 | int jobsComplete;\ | ||
| 77 | int jobs_complete = -1;\ | ||
| 78 | float *progTime = malloc(sizeof(float)*maxJobs*output);\ | ||
| 79 | memset(progTime, 0, sizeof(float)*maxJobs*output);\ | ||
| 80 | char fileName[64];\ | ||
| 81 | float *mmdc_read = malloc(sizeof(float)*maxJobs*output);\ | ||
| 82 | float *mmdc_write = malloc(sizeof(float)*maxJobs*output);\ | ||
| 83 | memset(mmdc_read, 0, sizeof(float)*maxJobs*output);\ | ||
| 84 | memset(mmdc_write, 0, sizeof(float)*maxJobs*output);\ | ||
| 85 | if (strlen(runID) + 5 > sizeof(fileName)) {\ | ||
| 86 | fprintf(stderr, "Run ID is too large! Keep it to less than 60 characters.\n");\ | ||
| 87 | exit(1);\ | 97 | exit(1);\ |
| 88 | }\ | 98 | }\ |
| 89 | strcpy(fileName, runID);\ | 99 | _rt_jobs_complete = 0;\ |
| 90 | strcat(fileName, ".txt");\ | ||
| 91 | mlockall(MCL_CURRENT || MCL_FUTURE); | 100 | mlockall(MCL_CURRENT || MCL_FUTURE); |
| 92 | 101 | ||
| 93 | #define SETUP_MMDC \ | 102 | #define SETUP_MMDC \ |
| 94 | MMDC_PROFILE_RES_t mmdc_res; \ | 103 | _rt_mmdc_read = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\ |
| 104 | _rt_mmdc_write = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\ | ||
| 105 | if (!_rt_mmdc_read || !_rt_mmdc_write) {\ | ||
| 106 | perror("Unable to allocate buffer for MMDC data");\ | ||
| 107 | exit(1);\ | ||
| 108 | }\ | ||
| 109 | MMDC_PROFILE_RES_t mmdc_res;\ | ||
| 95 | memset(&mmdc_res, 0, sizeof(MMDC_PROFILE_RES_t));\ | 110 | memset(&mmdc_res, 0, sizeof(MMDC_PROFILE_RES_t));\ |
| 96 | int fd = open("/dev/mem", O_RDWR, 0);\ | 111 | int fd = open("/dev/mem", O_RDWR, 0);\ |
| 97 | if (fd < 0) {\ | 112 | if (fd < 0) {\ |
| @@ -107,9 +122,8 @@ extern int sched_getcpu(); | |||
| 107 | msync(&(mmdc->madpcr1),4,MS_SYNC); | 122 | msync(&(mmdc->madpcr1),4,MS_SYNC); |
| 108 | 123 | ||
| 109 | #define SETUP_LITMUS \ | 124 | #define SETUP_LITMUS \ |
| 110 | unsigned int cpu = atoi(thisCore); \ | ||
| 111 | unsigned int wait = 0; \ | 125 | unsigned int wait = 0; \ |
| 112 | if (be_migrate_to_domain(cpu) < 0) { \ | 126 | if (be_migrate_to_domain(_rt_core) < 0) { \ |
| 113 | perror("Unable to migrate to specified CPU"); \ | 127 | perror("Unable to migrate to specified CPU"); \ |
| 114 | exit(1); \ | 128 | exit(1); \ |
| 115 | } \ | 129 | } \ |
| @@ -176,54 +190,6 @@ extern int sched_getcpu(); | |||
| 176 | } \ | 190 | } \ |
| 177 | reservation_destroy(gettid(), rt_param.cpu); | 191 | reservation_destroy(gettid(), rt_param.cpu); |
| 178 | 192 | ||
| 179 | #if MMDC_PROF | ||
| 180 | #define SAVE_RESULTS \ | ||
| 181 | if(jobs_complete >= maxJobs) {\ | ||
| 182 | fprintf(stderr, "Max jobs setting too small! Trying to record job #%d when we only have space for %d jobs. Exiting...\n", jobs_complete, maxJobs);\ | ||
| 183 | exit(1);\ | ||
| 184 | }\ | ||
| 185 | if(jobs_complete > -1 && output) {\ | ||
| 186 | progTime[jobs_complete] = _end.tv_sec - _start.tv_sec;\ | ||
| 187 | progTime[jobs_complete] *= 1000000000;\ | ||
| 188 | progTime[jobs_complete] += _end.tv_nsec - _start.tv_nsec;\ | ||
| 189 | mmdc_read[jobs_complete] = mmdc_res.read_bytes;\ | ||
| 190 | mmdc_write[jobs_complete] = mmdc_res.write_bytes;\ | ||
| 191 | } | ||
| 192 | #else | ||
| 193 | #define SAVE_RESULTS \ | ||
| 194 | if(jobs_complete >= maxJobs) {\ | ||
| 195 | fprintf(stderr, "Max jobs setting too small! Trying to record job #%d when we only have space for %d jobs. Exiting...\n", jobs_complete, maxJobs);\ | ||
| 196 | exit(1);\ | ||
| 197 | }\ | ||
| 198 | if(jobs_complete > -1 && output) {\ | ||
| 199 | progTime[jobs_complete] = _end.tv_sec - _start.tv_sec;\ | ||
| 200 | progTime[jobs_complete] *= 1000000000;\ | ||
| 201 | progTime[jobs_complete] += _end.tv_nsec - _start.tv_nsec;\ | ||
| 202 | } | ||
| 203 | #endif | ||
| 204 | |||
| 205 | |||
| 206 | #if LITMUS | ||
| 207 | #define WRITE_TO_FILE WRITE_TO_FILE_ITRNL CLEANUP_LITMUS | ||
| 208 | #else | ||
| 209 | #define WRITE_TO_FILE WRITE_TO_FILE_ITRNL | ||
| 210 | #endif | ||
| 211 | |||
| 212 | #define WRITE_TO_FILE_ITRNL if (output){\ | ||
| 213 | munlockall();\ | ||
| 214 | FILE *fp=fopen(fileName, "a");\ | ||
| 215 | if (fp == NULL) {\ | ||
| 216 | perror("Unable to open output file");\ | ||
| 217 | exit(1);\ | ||
| 218 | }\ | ||
| 219 | for (int i = 0; i <= jobs_complete; i++){\ | ||
| 220 | fprintf(fp, "%s none %u none %d %.f %s %d %.f %.f \n",\ | ||
| 221 | thisProgram, thisCore, maxJobs,\ | ||
| 222 | progTime[i], runID, i, mmdc_read[i], mmdc_write[i]);\ | ||
| 223 | }\ | ||
| 224 | fclose(fp);\ | ||
| 225 | } | ||
| 226 | |||
| 227 | #if __arm__ | 193 | #if __arm__ |
| 228 | // On ARM, manually flush the cache | 194 | // On ARM, manually flush the cache |
| 229 | #define FLUSH_CACHES \ | 195 | #define FLUSH_CACHES \ |
| @@ -247,53 +213,138 @@ extern int sched_getcpu(); | |||
| 247 | fclose(fp); | 213 | fclose(fp); |
| 248 | #endif | 214 | #endif |
| 249 | 215 | ||
| 216 | // Buffer timing result from a single job | ||
| 217 | static void _rt_save_job_result() { | ||
| 218 | if (_rt_jobs_complete >= _rt_max_jobs) { | ||
| 219 | fprintf(stderr, "Max jobs setting too small! Trying to record job #%ld when we only have space for %ld jobs. Exiting...\n", _rt_jobs_complete, _rt_max_jobs); | ||
| 220 | exit(1); | ||
| 221 | } | ||
| 222 | if (_rt_jobs_complete > -1 && _rt_will_output) { | ||
| 223 | _rt_exec_time[_rt_jobs_complete] = _rt_end.tv_sec - _rt_start.tv_sec; | ||
| 224 | _rt_exec_time[_rt_jobs_complete] *= 1e9; | ||
| 225 | _rt_exec_time[_rt_jobs_complete] += _rt_end.tv_nsec - _rt_start.tv_nsec; | ||
| 250 | #if MMDC_PROF | 226 | #if MMDC_PROF |
| 251 | #define START_TIMER \ | 227 | _rt_mmdc_read[_rt_jobs_complete] = mmdc_res.read_bytes; |
| 252 | /* This disables profiling, resets the counters, clears the overflow bit, and enables profiling */ \ | 228 | _rt_mmdc_write[_rt_jobs_complete] = mmdc_res.write_bytes; |
| 253 | start_mmdc_profiling(mmdc); \ | ||
| 254 | /*nanosleep(&(struct timespec){0, ms2ns(999)}, NULL);*/ \ | ||
| 255 | clock_gettime(CLOCK_MONOTONIC, &_start); | ||
| 256 | #else | ||
| 257 | #define START_TIMER clock_gettime(CLOCK_MONOTONIC, &_start); | ||
| 258 | #endif | 229 | #endif |
| 230 | } | ||
| 231 | } | ||
| 259 | 232 | ||
| 233 | // Save all buffered timing results to disk | ||
| 234 | static void _rt_write_to_file() { | ||
| 235 | char fileName[_RT_FILENAME_LEN]; | ||
| 236 | FILE *fp; | ||
| 237 | if (!_rt_will_output) | ||
| 238 | return; | ||
