aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/gpu_affinity.c
blob: 43171390bed710dcbd509655107ea4da980b00ad (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

#ifdef CONFIG_LITMUS_NVIDIA

#include <linux/sched.h>
#include <litmus/litmus.h>
#include <litmus/gpu_affinity.h>

static void update_estimate(feedback_est_t* fb, fp_t* a, fp_t* b, lt_t observed)
{
	fp_t err, new;
	fp_t actual = _frac(observed, 1); // observed is in ns, so beware of overflow!
	
	err = _sub(actual, fb->est);
	new = _add(_mul(*a, err),
			   _mul(*b, fb->accum_err));
	
	fb->est = new;
	fb->accum_err = _add(fb->accum_err, err);
}

void update_gpu_estimate(struct task_struct *t, lt_t observed)
{
	feedback_est_t *fb = &(tsk_rt(t)->gpu_migration_est[tsk_rt(t)->gpu_migration]);
	
	TRACE_TASK(t, "GPU est update before (dist = %d): %d.%d\n", 
			   tsk_rt(t)->gpu_migration,
			   _fp_to_integer(fb->est),
			   _point(fb->est));
	
	update_estimate(fb,
					&tsk_rt(t)->gpu_fb_param_a,
					&tsk_rt(t)->gpu_fb_param_b,
					observed);
	
	TRACE_TASK(t, "GPU est update after (dist = %d): %d.%d\n", 
			   tsk_rt(t)->gpu_migration,
			   _fp_to_integer(fb->est),
			   _point(fb->est));	
}

gpu_migration_dist_t gpu_migration_distance(int a, int b)
{
	// GPUs organized in a binary hierarchy, no more than 2^MIG_LAST GPUs
	int i;
	int level;
	int max_level;
	
	if(unlikely(a < 0 || b < 0)) {
		return MIG_LAST;
	}
	
	if(a == b) {
		return MIG_LOCAL;
	}
	
	for(i = 1, level = 2, max_level = 1<<MIG_LAST;
		level <= max_level;
		++i, level <<= 1) {
		if(a/level == b/level) {
			return (gpu_migration_dist_t)(i);
		}
	}
	
	WARN_ON(1);
	return MIG_LAST;
}




#endif