Commit dbf28efd authored by Paul E. McKenney's avatar Paul E. McKenney

refperf: Provide module parameter to specify number of experiments

The current code uses the number of threads both to limit the number
of threads and to specify the number of experiments, but also varies
the number of threads as the experiments progress.  This commit takes
a different approach by adding an refperf.nruns module parameter that
specifies the number of experiments, and furthermore uses the same
number of threads for each experiment.

Cc: Joel Fernandes (Google) <joel@joelfernandes.org>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 8fc28783
...@@ -83,12 +83,6 @@ struct reader_task { ...@@ -83,12 +83,6 @@ struct reader_task {
atomic_t start; atomic_t start;
wait_queue_head_t wq; wait_queue_head_t wq;
u64 last_duration_ns; u64 last_duration_ns;
// The average latency When 1..<this reader> are concurrently
// running an experiment. For example, if this reader_task is
// of index 5 in the reader_tasks array, then result is for
// 6 cores.
u64 result_avg;
}; };
static struct task_struct *shutdown_task; static struct task_struct *shutdown_task;
...@@ -289,12 +283,12 @@ ref_perf_reader(void *arg) ...@@ -289,12 +283,12 @@ ref_perf_reader(void *arg)
return 0; return 0;
} }
void reset_readers(int n) void reset_readers(void)
{ {
int i; int i;
struct reader_task *rt; struct reader_task *rt;
for (i = 0; i < n; i++) { for (i = 0; i < nreaders; i++) {
rt = &(reader_tasks[i]); rt = &(reader_tasks[i]);
rt->last_duration_ns = 0; rt->last_duration_ns = 0;
...@@ -314,7 +308,7 @@ u64 process_durations(int n) ...@@ -314,7 +308,7 @@ u64 process_durations(int n)
sprintf(buf, "Experiment #%d (Format: <THREAD-NUM>:<Total loop time in ns>)", sprintf(buf, "Experiment #%d (Format: <THREAD-NUM>:<Total loop time in ns>)",
exp_idx); exp_idx);
for (i = 0; i <= n && !torture_must_stop(); i++) { for (i = 0; i < n && !torture_must_stop(); i++) {
rt = &(reader_tasks[i]); rt = &(reader_tasks[i]);
sprintf(buf1, "%d: %llu\t", i, rt->last_duration_ns); sprintf(buf1, "%d: %llu\t", i, rt->last_duration_ns);
...@@ -342,11 +336,15 @@ static int main_func(void *arg) ...@@ -342,11 +336,15 @@ static int main_func(void *arg)
int exp, r; int exp, r;
char buf1[64]; char buf1[64];
char buf[512]; char buf[512];
u64 *result_avg;
set_cpus_allowed_ptr(current, cpumask_of(nreaders % nr_cpu_ids)); set_cpus_allowed_ptr(current, cpumask_of(nreaders % nr_cpu_ids));
set_user_nice(current, MAX_NICE); set_user_nice(current, MAX_NICE);
VERBOSE_PERFOUT("main_func task started"); VERBOSE_PERFOUT("main_func task started");
result_avg = kzalloc(nruns * sizeof(*result_avg), GFP_KERNEL);
if (!result_avg)
VERBOSE_PERFOUT_ERRSTRING("out of memory");
atomic_inc(&n_init); atomic_inc(&n_init);
// Wait for all threads to start. // Wait for all threads to start.
...@@ -355,22 +353,24 @@ static int main_func(void *arg) ...@@ -355,22 +353,24 @@ static int main_func(void *arg)
schedule_timeout_interruptible(holdoff * HZ); schedule_timeout_interruptible(holdoff * HZ);
// Start exp readers up per experiment // Start exp readers up per experiment
for (exp = 0; exp < nreaders && !torture_must_stop(); exp++) { for (exp = 0; exp < nruns && !torture_must_stop(); exp++) {
if (!result_avg)
break;
if (torture_must_stop()) if (torture_must_stop())
goto end; goto end;
reset_readers(exp); reset_readers();
atomic_set(&nreaders_exp, exp + 1); atomic_set(&nreaders_exp, nreaders);
exp_idx = exp; exp_idx = exp;
for (r = 0; r <= exp; r++) { for (r = 0; r < nreaders; r++) {
atomic_set(&reader_tasks[r].start, 1); atomic_set(&reader_tasks[r].start, 1);
wake_up(&reader_tasks[r].wq); wake_up(&reader_tasks[r].wq);
} }
VERBOSE_PERFOUT("main_func: experiment started, waiting for %d readers", VERBOSE_PERFOUT("main_func: experiment started, waiting for %d readers",
exp); nreaders);
wait_event(main_wq, wait_event(main_wq,
!atomic_read(&nreaders_exp) || torture_must_stop()); !atomic_read(&nreaders_exp) || torture_must_stop());
...@@ -380,7 +380,7 @@ static int main_func(void *arg) ...@@ -380,7 +380,7 @@ static int main_func(void *arg)
if (torture_must_stop()) if (torture_must_stop())
goto end; goto end;
reader_tasks[exp].result_avg = 1000 * process_durations(exp) / ((exp + 1) * loops); result_avg[exp] = 1000 * process_durations(nreaders) / (nreaders * loops);
} }
// Print the average of all experiments // Print the average of all experiments
...@@ -390,12 +390,15 @@ static int main_func(void *arg) ...@@ -390,12 +390,15 @@ static int main_func(void *arg)
strcat(buf, "\n"); strcat(buf, "\n");
strcat(buf, "Threads\tTime(ns)\n"); strcat(buf, "Threads\tTime(ns)\n");
for (exp = 0; exp < nreaders; exp++) { for (exp = 0; exp < nruns; exp++) {
sprintf(buf1, "%d\t%llu.%03d\n", exp + 1, reader_tasks[exp].result_avg / 1000, (int)(reader_tasks[exp].result_avg % 1000)); if (!result_avg)
break;
sprintf(buf1, "%d\t%llu.%03d\n", exp + 1, result_avg[exp] / 1000, (int)(result_avg[exp] % 1000));
strcat(buf, buf1); strcat(buf, buf1);
} }
PERFOUT("%s", buf); if (result_avg)
PERFOUT("%s", buf);
// This will shutdown everything including us. // This will shutdown everything including us.
if (shutdown) { if (shutdown) {
...@@ -416,8 +419,8 @@ static void ...@@ -416,8 +419,8 @@ static void
ref_perf_print_module_parms(struct ref_perf_ops *cur_ops, const char *tag) ref_perf_print_module_parms(struct ref_perf_ops *cur_ops, const char *tag)
{ {
pr_alert("%s" PERF_FLAG pr_alert("%s" PERF_FLAG
"--- %s: verbose=%d shutdown=%d holdoff=%d loops=%ld nreaders=%d\n", perf_type, tag, "--- %s: verbose=%d shutdown=%d holdoff=%d loops=%ld nreaders=%d nruns=%d\n", perf_type, tag,
verbose, shutdown, holdoff, loops, nreaders); verbose, shutdown, holdoff, loops, nreaders, nruns);
} }
static void static void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment