|
@@ -17,6 +17,7 @@
|
|
|
#include <starpu.h>
|
|
|
#include <starpu_profiling.h>
|
|
|
#include <profiling/profiling.h>
|
|
|
+#include <core/workers.h>
|
|
|
#include <common/config.h>
|
|
|
#include <common/utils.h>
|
|
|
#include <common/timing.h>
|
|
@@ -26,6 +27,14 @@
|
|
|
static struct starpu_worker_profiling_info worker_info[STARPU_NMAXWORKERS];
|
|
|
static pthread_mutex_t worker_info_mutex[STARPU_NMAXWORKERS];
|
|
|
|
|
|
+/* In case the worker is still sleeping when the user request profiling info,
|
|
|
+ * we need to account for the time elasped while sleeping. */
|
|
|
+static unsigned worker_registered_sleeping_start[STARPU_NMAXWORKERS];
|
|
|
+static struct timespec sleeping_start_date[STARPU_NMAXWORKERS];
|
|
|
+
|
|
|
+static unsigned worker_registered_executing_start[STARPU_NMAXWORKERS];
|
|
|
+static struct timespec executing_start_date[STARPU_NMAXWORKERS];
|
|
|
+
|
|
|
/*
|
|
|
* Global control of profiling
|
|
|
*/
|
|
@@ -46,12 +55,6 @@ int starpu_profiling_status_set(int status)
|
|
|
int worker;
|
|
|
for (worker = 0; worker < STARPU_NMAXWORKERS; worker++)
|
|
|
_starpu_worker_reset_profiling_info(worker);
|
|
|
-
|
|
|
- /* In case there are blocked workers, we wake them up so that
|
|
|
- * the sleeping is measured from the time we activate
|
|
|
- * profiling, and not when the worker is awoken for the first
|
|
|
- * time later on. */
|
|
|
- starpu_wake_all_blocked_workers();
|
|
|
}
|
|
|
|
|
|
return prev_value;
|
|
@@ -90,9 +93,9 @@ struct starpu_task_profiling_info *_starpu_allocate_profiling_info_if_needed(voi
|
|
|
info = calloc(1, sizeof(struct starpu_task_profiling_info));
|
|
|
STARPU_ASSERT(info);
|
|
|
|
|
|
- info->submit_time = -ENOSYS;
|
|
|
- info->start_time = -ENOSYS;
|
|
|
- info->end_time = -ENOSYS;
|
|
|
+ starpu_timespec_clear(&info->submit_time);
|
|
|
+ starpu_timespec_clear(&info->start_time);
|
|
|
+ starpu_timespec_clear(&info->end_time);
|
|
|
}
|
|
|
|
|
|
return info;
|
|
@@ -104,15 +107,38 @@ struct starpu_task_profiling_info *_starpu_allocate_profiling_info_if_needed(voi
|
|
|
|
|
|
static void _do_starpu_worker_reset_profiling_info(int workerid)
|
|
|
{
|
|
|
- worker_info[workerid].start_time = (int64_t)_starpu_timing_now();
|
|
|
+ starpu_clock_gettime(&worker_info[workerid].start_time);
|
|
|
|
|
|
/* This is computed in a lazy fashion when the application queries
|
|
|
* profiling info. */
|
|
|
- worker_info[workerid].total_time = -ENOSYS;
|
|
|
+ starpu_timespec_clear(&worker_info[workerid].total_time);
|
|
|
+
|
|
|
+ starpu_timespec_clear(&worker_info[workerid].executing_time);
|
|
|
+ starpu_timespec_clear(&worker_info[workerid].sleeping_time);
|
|
|
|
|
|
- worker_info[workerid].executing_time = 0;
|
|
|
- worker_info[workerid].sleeping_time = 0;
|
|
|
worker_info[workerid].executed_tasks = 0;
|
|
|
+
|
|
|
+ /* We detect if the worker is already sleeping or doing some
|
|
|
+ * computation */
|
|
|
+ starpu_worker_status status = _starpu_worker_get_status(workerid);
|
|
|
+
|
|
|
+ if (status == STATUS_SLEEPING)
|
|
|
+ {
|
|
|
+ worker_registered_sleeping_start[workerid] = 1;
|
|
|
+ starpu_clock_gettime(&sleeping_start_date[workerid]);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ worker_registered_sleeping_start[workerid] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (status == STATUS_EXECUTING)
|
|
|
+ {
|
|
|
+ worker_registered_executing_start[workerid] = 1;
|
|
|
+ starpu_clock_gettime(&executing_start_date[workerid]);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ worker_registered_executing_start[workerid] = 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void _starpu_worker_reset_profiling_info(int workerid)
|
|
@@ -122,15 +148,65 @@ void _starpu_worker_reset_profiling_info(int workerid)
|
|
|
PTHREAD_MUTEX_UNLOCK(&worker_info_mutex[workerid]);
|
|
|
}
|
|
|
|
|
|
-void _starpu_worker_update_profiling_info(int workerid, int64_t executing_time,
|
|
|
- int64_t sleeping_time, int executed_tasks)
|
|
|
+void _starpu_worker_register_sleeping_start_date(int workerid, struct timespec *sleeping_start)
|
|
|
{
|
|
|
if (profiling)
|
|
|
{
|
|
|
PTHREAD_MUTEX_LOCK(&worker_info_mutex[workerid]);
|
|
|
-
|
|
|
- worker_info[workerid].executing_time += executing_time;
|
|
|
- worker_info[workerid].sleeping_time += sleeping_time;
|
|
|
+ worker_registered_sleeping_start[workerid] = 1;
|
|
|
+ memcpy(&sleeping_start_date[workerid], sleeping_start, sizeof(struct timespec));
|
|
|
+ PTHREAD_MUTEX_UNLOCK(&worker_info_mutex[workerid]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void _starpu_worker_register_executing_start_date(int workerid, struct timespec *executing_start)
|
|
|
+{
|
|
|
+ if (profiling)
|
|
|
+ {
|
|
|
+ PTHREAD_MUTEX_LOCK(&worker_info_mutex[workerid]);
|
|
|
+ worker_registered_executing_start[workerid] = 1;
|
|
|
+ memcpy(&executing_start_date[workerid], executing_start, sizeof(struct timespec));
|
|
|
+ PTHREAD_MUTEX_UNLOCK(&worker_info_mutex[workerid]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void _starpu_worker_update_profiling_info_sleeping(int workerid, struct timespec *sleeping_start, struct timespec *sleeping_end)
|
|
|
+{
|
|
|
+ if (profiling)
|
|
|
+ {
|
|
|
+ PTHREAD_MUTEX_LOCK(&worker_info_mutex[workerid]);
|
|
|
+
|
|
|
+ /* Perhaps that profiling was enabled while the worker was
|
|
|
+ * already blocked, so we don't measure (end - start), but
|
|
|
+ * (end - max(start,worker_start)) where worker_start is the
|
|
|
+ * date of the previous profiling info reset on the worker */
|
|
|
+ struct timespec *worker_start = &worker_info[workerid].start_time;
|
|
|
+ if (starpu_timespec_cmp(sleeping_start, worker_start, <))
|
|
|
+ {
|
|
|
+ /* sleeping_start < worker_start */
|
|
|
+ sleeping_start = worker_start;
|
|
|
+ }
|
|
|
+
|
|
|
+ struct timespec sleeping_time;
|
|
|
+ starpu_timespec_sub(sleeping_end, sleeping_start, &sleeping_time);
|
|
|
+
|
|
|
+ starpu_timespec_accumulate(&worker_info[workerid].sleeping_time, &sleeping_time);
|
|
|
+
|
|
|
+ worker_registered_sleeping_start[workerid] = 0;
|
|
|
+
|
|
|
+ PTHREAD_MUTEX_UNLOCK(&worker_info_mutex[workerid]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void _starpu_worker_update_profiling_info_executing(int workerid, struct timespec *executing_time, int executed_tasks)
|
|
|
+{
|
|
|
+ if (profiling)
|
|
|
+ {
|
|
|
+ PTHREAD_MUTEX_LOCK(&worker_info_mutex[workerid]);
|
|
|
+
|
|
|
+ starpu_timespec_accumulate(&worker_info[workerid].executing_time, executing_time);
|
|
|
+
|
|
|
worker_info[workerid].executed_tasks += executed_tasks;
|
|
|
|
|
|
PTHREAD_MUTEX_UNLOCK(&worker_info_mutex[workerid]);
|
|
@@ -147,8 +223,28 @@ int starpu_worker_get_profiling_info(int workerid, struct starpu_worker_profilin
|
|
|
if (info)
|
|
|
{
|
|
|
/* The total time is computed in a lazy fashion */
|
|
|
- int64_t total_time = ((int64_t)_starpu_timing_now()) - worker_info[workerid].start_time;
|
|
|
- worker_info[workerid].total_time = total_time;
|
|
|
+ struct timespec now;
|
|
|
+ starpu_clock_gettime(&now);
|
|
|
+
|
|
|
+ /* In case some worker is currently sleeping, we take into
|
|
|
+ * account the time spent since it registered. */
|
|
|
+ if (worker_registered_sleeping_start[workerid])
|
|
|
+ {
|
|
|
+ struct timespec sleeping_time;
|
|
|
+ starpu_timespec_sub(&now, &sleeping_start_date[workerid], &sleeping_time);
|
|
|
+ starpu_timespec_accumulate(&worker_info[workerid].sleeping_time, &sleeping_time);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (worker_registered_executing_start[workerid])
|
|
|
+ {
|
|
|
+ struct timespec executing_time;
|
|
|
+ starpu_timespec_sub(&now, &executing_start_date[workerid], &executing_time);
|
|
|
+ starpu_timespec_accumulate(&worker_info[workerid].executing_time, &executing_time);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* total_time = now - start_time */
|
|
|
+ starpu_timespec_sub(&now, &worker_info[workerid].start_time,
|
|
|
+ &worker_info[workerid].total_time);
|
|
|
|
|
|
memcpy(info, &worker_info[workerid], sizeof(struct starpu_worker_profiling_info));
|
|
|
}
|