static void print_results(void) { int i; int t; unsigned long long tasks_max[nr_tasks]; unsigned long long tasks_min[nr_tasks]; unsigned long long tasks_avg[nr_tasks]; memset(tasks_max, 0, sizeof(tasks_max[0])*nr_tasks); memset(tasks_min, 0xff, sizeof(tasks_min[0])*nr_tasks); memset(tasks_avg, 0, sizeof(tasks_avg[0])*nr_tasks); printf("Iter: "); for (t = 0; t < nr_tasks; t++) printf("%6d ", t); printf("\n"); for (t = 0; t < nr_tasks; t++) { tasks_max[t] = stats_max(&intervals[t]); tasks_min[t] = stats_min(&intervals[t]); tasks_avg[t] = stats_avg(&intervals[t]); } for (i = 0; i < nr_runs; i++) { printf("%4d: ", i); for (t = 0; t < nr_tasks; t++) printf("%6ld ", intervals[t].records[i].y); printf("\n"); printf(" len: "); for (t = 0; t < nr_tasks; t++) printf("%6ld ", intervals_length[t].records[i].y); printf("\n"); printf(" loops: "); for (t = 0; t < nr_tasks; t++) printf("%6ld ", intervals_loops[t].records[i].y); printf("\n"); printf("\n"); } printf("Parent pid: %d\n", getpid()); for (t = 0; t < nr_tasks; t++) { printf(" Task %d (prio %d) (pid %ld):\n", t, t + prio_start, thread_pids[t]); printf(" Max: %lld us\n", tasks_max[t]); printf(" Min: %lld us\n", tasks_min[t]); printf(" Tot: %lld us\n", tasks_avg[t] * nr_runs); printf(" Avg: %lld us\n", tasks_avg[t]); printf("\n"); } printf(" Result: %s\n", (check < 0) ? "FAIL" : "PASS"); }
void * high_prio_thread(void *arg) { nsec_t high_start, high_end, high_get_lock; unsigned int i; stats_container_init(&cpu_delay_dat, iterations); stats_container_init(&cpu_delay_hist, HIST_BUCKETS); stats_quantiles_init(&cpu_delay_quantiles, (int)log10(iterations)); printf("High prio thread started\n"); for (i = 0; i < iterations; i++) { /* Wait for all threads to reach barrier wait. When woken up, low prio thread will own the mutex */ pthread_barrier_wait(&bar1); high_start = rt_gettime(); pthread_mutex_lock(&lock); high_end = rt_gettime(); high_get_lock = high_end - low_unlock; busy_work_ms(high_work_time); pthread_mutex_unlock(&lock); rec.x = i; rec.y = high_get_lock / NS_PER_US; stats_container_append(&cpu_delay_dat, rec); /* Wait for all threads to finish this iteration */ pthread_barrier_wait(&bar2); } stats_hist(&cpu_delay_hist, &cpu_delay_dat); stats_container_save("samples", "pi_perf Latency Scatter Plot", "Iteration", "Latency (us)", &cpu_delay_dat, "points"); stats_container_save("hist", "pi_perf Latency Histogram", "Latency (us)", "Samples", &cpu_delay_hist, "steps"); printf("Time taken for high prio thread to get the lock once released by low prio thread\n"); printf("Min delay = %ld us\n", stats_min(&cpu_delay_dat)); printf("Max delay = %ld us\n", stats_max(&cpu_delay_dat)); printf("Average delay = %4.2f us\n", stats_avg(&cpu_delay_dat)); printf("Standard Deviation = %4.2f us\n", stats_stddev(&cpu_delay_dat)); printf("Quantiles:\n"); stats_quantiles_calc(&cpu_delay_dat, &cpu_delay_quantiles); stats_quantiles_print(&cpu_delay_quantiles); max_pi_delay = stats_max(&cpu_delay_dat); return NULL; }
int periodic_thread(nsec_t period, int iterations, int loops) { stats_container_t dat; stats_container_t hist; stats_quantiles_t quantiles; stats_record_t rec; int i = 0; int fail = 0; nsec_t next, now; nsec_t exe_start, exe_end, exe_time; char *samples_filename; char *hist_filename; stats_container_init(&dat, iterations); stats_container_init(&hist, HIST_BUCKETS); stats_quantiles_init(&quantiles, (int)log10(iterations)); if (asprintf(&samples_filename, "%s-samples", filename_prefix) == -1) { fprintf(stderr, "Failed to allocate string for samples filename\n"); return -1; } if (asprintf(&hist_filename, "%s-hist", filename_prefix) == -1) { fprintf(stderr, "Failed to allocate string for samples filename\n"); return -1; } next = rt_gettime(); while (i < iterations) { next += period; now = rt_gettime(); if (now > next) { printf("Missed period, aborting (didn't get scheduled in time)\n"); fail = 1; break; } exe_start = rt_gettime(); calc(loops); exe_end = rt_gettime(); exe_time = exe_end - exe_start; rec.x = i; rec.y = exe_time/NS_PER_US; stats_container_append(&dat, rec); i++; now = rt_gettime(); if (now > next) { printf("Missed period, aborting (calc took too long)\n"); fail = 1; break; } rt_nanosleep(next - now); } stats_container_save(samples_filename, "Periodic CPU Load Scatter Plot",\ "Iteration", "Runtime (us)", &dat, "points"); stats_container_save(hist_filename, "Periodic CPU Load Histogram",\ "Runtime (us)", "Samples", &hist, "steps"); printf(" Execution Time Statistics:\n"); printf("Min: %ld us\n", stats_min(&dat)); printf("Max: %ld us\n", stats_max(&dat)); printf("Avg: %.4f us\n", stats_avg(&dat)); printf("StdDev: %.4f us\n", stats_stddev(&dat)); printf("Quantiles:\n"); stats_quantiles_calc(&dat, &quantiles); stats_quantiles_print(&quantiles); printf("Criteria: no missed periods\n"); printf("Result: %s\n", fail ? "FAIL":"PASS"); free(samples_filename); free(hist_filename); return fail; }
void *signal_receiving_thread(void *arg) { int i, ret, sig; long delta; long max, min; sigset_t set, oset; stats_container_t dat; stats_container_t hist; stats_quantiles_t quantiles; stats_record_t rec; stats_container_init(&dat, ITERATIONS); stats_container_init(&hist, HIST_BUCKETS); stats_quantiles_init(&quantiles, (int)log10(ITERATIONS)); debug(DBG_DEBUG, "Signal receiving thread running\n"); if ((sigaddset(&set, SIGNALNUMBER))) { perror("sigaddset:"); exit(1); } if ((ret = pthread_sigmask(SIG_BLOCK, &set, &oset))) { printf("pthread_sigmask returned %d\n", ret); exit(1); } /* Let the sending thread know that receiver is ready */ atomic_set(1, &flag); debug(DBG_DEBUG, "Signal receiving thread ready to receive\n"); if (latency_threshold) { latency_trace_enable(); latency_trace_start(); } /* Warm up */ for (i = 0; i < 5; i++) { sigwait(&set, &sig); atomic_set(1, &flag); } max = min = 0; fail = 0; debug(DBG_INFO, "\n\n"); for (i = 0; i < ITERATIONS; i++) { sigwait(&set, &sig); end = rt_gettime(); delta = (end - begin)/NS_PER_US; rec.x = i; rec.y = delta; stats_container_append(&dat, rec); if (i == 0 || delta < min) min = delta; if (delta > max) max = delta; if (delta > pass_criteria) fail++; debug(DBG_INFO, "Iteration %d: Took %ld us. Max = %ld us, " "Min = %ld us\n", i, delta, max, min); fflush(stdout); buffer_print(); if (latency_threshold && (delta > latency_threshold)) { atomic_set(2, &flag); break; } atomic_set(1, &flag); } if (latency_threshold) { latency_trace_stop(); if (i != ITERATIONS) { printf("Latency threshold (%luus) exceeded at iteration %d\n", latency_threshold, i); fflush(stdout); buffer_print(); latency_trace_print(); stats_container_resize(&dat, i + 1); } } stats_hist(&hist, &dat); stats_container_save("samples", "pthread_kill Latency Scatter Plot", "Iteration", "Latency (us)", &dat, "points"); stats_container_save("hist", "pthread_kill Latency Histogram", "Latency (us)", "Samples", &hist, "steps"); printf("\n"); printf("Min: %lu us\n", stats_min(&dat)); printf("Max: %lu us\n", stats_max(&dat)); printf("Avg: %.4f us\n", stats_avg(&dat)); printf("StdDev: %.4f us\n", stats_stddev(&dat)); printf("Quantiles:\n"); stats_quantiles_calc(&dat, &quantiles); stats_quantiles_print(&quantiles); printf("Failures: %d\n", fail); printf("Criteria: Time < %d us\n", (int)pass_criteria); printf("Result: %s", fail ? "FAIL" : "PASS"); printf("\n\n"); return NULL; }
int main(int argc, char *argv[]) { int i; setup(); rt_init("hi:", parse_args, argc, argv); if (iterations < 100) { fprintf(stderr, "Number of iteration cannot be less than 100.\n"); exit(1); } printf("------------------------------------\n"); printf("Periodic CPU Load Execution Variance\n"); printf("------------------------------------\n\n"); printf("Running %d iterations per thread\n", iterations); printf("Thread Group A:\n"); printf(" threads: %d\n", THREADS_PER_GROUP); printf(" priority: %d\n", PRIO_A); printf(" period: %d ms\n", PERIOD_A/NS_PER_MS); printf("Thread Group B:\n"); printf(" threads: %d\n", THREADS_PER_GROUP); printf(" priority: %d\n", PRIO_B); printf(" period: %d ms\n", PERIOD_B/NS_PER_MS); printf("Thread Group C:\n"); printf(" threads: %d\n", THREADS_PER_GROUP); printf(" priority: %d\n", PRIO_C); printf(" period: %d ms\n", PERIOD_C/NS_PER_MS); printf("\n"); for (i=0; i<(THREADS_PER_GROUP * NUM_GROUPS); i++) { stats_container_init(&dat[i], iterations); stats_quantiles_init(&quantiles[i], (int)log10(iterations)); } struct periodic_arg parg_a = {PERIOD_A, iterations, calc, (void *)CALC_LOOPS_A }; struct periodic_arg parg_b = {PERIOD_B, iterations, calc, (void *)CALC_LOOPS_B }; struct periodic_arg parg_c = {PERIOD_C, iterations, calc, (void *)CALC_LOOPS_C }; for (i=0; i < THREADS_PER_GROUP; i++) create_fifo_thread(periodic_thread, (void*)&parg_a, PRIO_A); for (i=0; i < THREADS_PER_GROUP; i++) create_fifo_thread(periodic_thread, (void*)&parg_b, PRIO_B); for (i=0; i < THREADS_PER_GROUP; i++) create_fifo_thread(periodic_thread, (void*)&parg_c, PRIO_C); join_threads(); printf("\nExecution Time Statistics:\n\n"); for (i=0; i<(THREADS_PER_GROUP * NUM_GROUPS); i++) { printf("TID %d (%c)\n", i, groupname[i>>2]); printf(" Min: %ld us\n", stats_min(&dat[i])); printf(" Max: %ld us\n", stats_max(&dat[i])); printf(" Avg: %f us\n", stats_avg(&dat[i])); printf(" StdDev: %f us\n\n", stats_stddev(&dat[i])); printf(" Quantiles:\n"); stats_quantiles_calc(&dat[i], &quantiles[i]); stats_quantiles_print(&quantiles[i]); printf("Criteria: TID %d did not miss a period\n", i); printf("Result: %s\n", fail[i] ? "FAIL":"PASS"); printf("\n"); if (fail[i]) ret = 1; } // FIXME: define pass criteria // printf("\nCriteria: latencies < %d us\n", PASS_US); // printf("Result: %s\n", ret ? "FAIL" : "PASS"); for (i=0; i<(THREADS_PER_GROUP * NUM_GROUPS); i++) { stats_container_free(&dat[i]); stats_quantiles_free(&quantiles[i]); } return ret; }
void main_thread(void) { int ret, i, j; nsec_t start, end; long smin = 0, smax = 0, cmin = 0, cmax = 0, delta = 0; float savg, cavg; int cpuid; if ( stats_container_init(&sdat, iterations) || stats_container_init(&shist, HIST_BUCKETS) || stats_container_init(&cdat, iterations) || stats_container_init(&chist, HIST_BUCKETS) ) { fprintf (stderr, "Cannot init stats container\n"); exit(1); } tids = malloc(sizeof(int) * numcpus); if (!tids) { perror("malloc"); exit(1); } memset(tids, 0, numcpus); cpuid = set_affinity(); if (cpuid == -1) { fprintf(stderr, "Main thread: Can't set affinity.\n"); exit(1); } /* run matrix mult operation sequentially */ curdat = &sdat; curdat->index = iterations-1; printf("\nRunning sequential operations\n"); start = rt_gettime(); for (i = 0; i < iterations; i++) matrix_mult_record(MATRIX_SIZE, i); end = rt_gettime(); delta = (long)((end - start)/NS_PER_US); savg = delta/iterations; /* don't use the stats record, use the total time recorded */ smin = stats_min(&sdat); smax = stats_max(&sdat); printf("Min: %ld us\n", smin); printf("Max: %ld us\n", smax); printf("Avg: %.4f us\n", savg); printf("StdDev: %.4f us\n", stats_stddev(&sdat)); if ( stats_hist(&shist, &sdat) || stats_container_save("sequential", "Matrix Multiplication Sequential Execution Runtime Scatter Plot", "Iteration", "Runtime (us)", &sdat, "points") || stats_container_save("sequential_hist", "Matrix Multiplicatoin Sequential Execution Runtime Histogram", "Runtime (us)", "Samples", &shist, "steps") ) { fprintf(stderr, "Warning: could not save sequential mults stats\n"); } pthread_barrier_init(&mult_start, NULL, numcpus+1); set_priority(PRIO); curdat = &cdat; curdat->index = iterations-1; online_cpu_id = -1; /* Redispatch cpus */ /* Create numcpus-1 concurrent threads */ for (j = 0; j < numcpus; j++) { tids[j] = create_fifo_thread(concurrent_thread, NULL, PRIO); if (tids[j] == -1) { printf("Thread creation failed (max threads exceeded?)\n"); exit(1); } } /* run matrix mult operation concurrently */ printf("\nRunning concurrent operations\n"); pthread_barrier_wait(&mult_start); start = rt_gettime(); join_threads(); end = rt_gettime(); delta = (long)((end - start)/NS_PER_US); cavg = delta/iterations; /* don't use the stats record, use the total time recorded */ cmin = stats_min(&cdat); cmax = stats_max(&cdat); printf("Min: %ld us\n", cmin); printf("Max: %ld us\n", cmax); printf("Avg: %.4f us\n", cavg); printf("StdDev: %.4f us\n", stats_stddev(&cdat)); if ( stats_hist(&chist, &cdat) || stats_container_save("concurrent", "Matrix Multiplication Concurrent Execution Runtime Scatter Plot", "Iteration", "Runtime (us)", &cdat, "points") || stats_container_save("concurrent_hist", "Matrix Multiplication Concurrent Execution Runtime Histogram", "Iteration", "Runtime (us)", &chist, "steps") ) { fprintf(stderr, "Warning: could not save concurrent mults stats\n"); } printf("\nConcurrent Multipliers:\n"); printf("Min: %.4f\n", (float)smin/cmin); printf("Max: %.4f\n", (float)smax/cmax); printf("Avg: %.4f\n", (float)savg/cavg); ret = 1; if (savg > (cavg * criteria)) ret = 0; printf("\nCriteria: %.2f * average concurrent time < average sequential time\n", criteria); printf("Result: %s\n", ret ? "FAIL" : "PASS"); return; }