diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2013-04-24 20:34:17 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2013-04-24 20:34:17 -0400 |
commit | e3935c7f68ce428e394eb53ea29ebef5509bcd7f (patch) | |
tree | 33e5cff0aae98c00ce777b18fbaed888171ad334 | |
parent | 76b0d79069973bd58cda6028c65a9edaa6d2ea73 (diff) |
integrated numa support and fixed p2p migration
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | gpu/gpuspin.cu | 53 | ||||
-rw-r--r-- | src/migration.c | 59 |
3 files changed, 100 insertions, 26 deletions
@@ -14,6 +14,11 @@ ARCH ?= ${host-arch} | |||
14 | # LITMUS_KERNEL -- where to find the litmus kernel? | 14 | # LITMUS_KERNEL -- where to find the litmus kernel? |
15 | LITMUS_KERNEL ?= ../litmus-rt | 15 | LITMUS_KERNEL ?= ../litmus-rt |
16 | 16 | ||
17 | # NUMA Support. Comment out to disable. Requires libnuma dev files. | ||
18 | # | ||
19 | # Enabling this option will ensure all memory resides on NUMA nodes | ||
20 | # that overlap clusters/partitions specified by a call to be_migrate*(). | ||
21 | NUMA_SUPPORT = dummyval | ||
17 | 22 | ||
18 | # ############################################################################## | 23 | # ############################################################################## |
19 | # Internal configuration. | 24 | # Internal configuration. |
@@ -62,8 +67,17 @@ CUFLAGS = ${flags-api} ${flags-cu-debug} ${flags-cu-optim} ${flags-cu-nvcc} ${f | |||
62 | CFLAGS = ${flags-debug} ${flags-misc} | 67 | CFLAGS = ${flags-debug} ${flags-misc} |
63 | LDFLAGS = ${flags-${ARCH}} | 68 | LDFLAGS = ${flags-${ARCH}} |
64 | 69 | ||
70 | ifdef NUMA_SUPPORT | ||
71 | CFLAGS += -DLITMUS_NUMA_SUPPORT | ||
72 | CPPFLAGS += -DLITMUS_NUMA_SUPPORT | ||
73 | CUFLAGS += -DLITMUS_NUMA_SUPPORT | ||
74 | endif | ||
75 | |||
65 | # how to link against liblitmus | 76 | # how to link against liblitmus |
66 | liblitmus-flags = -L${LIBLITMUS} -llitmus | 77 | liblitmus-flags = -L${LIBLITMUS} -llitmus |
78 | ifdef NUMA_SUPPORT | ||
79 | liblitmus-flags += -lnuma | ||
80 | endif | ||
67 | 81 | ||
68 | # how to link cuda | 82 | # how to link cuda |
69 | cuda-flags-i386 = -L/usr/local/cuda/lib | 83 | cuda-flags-i386 = -L/usr/local/cuda/lib |
diff --git a/gpu/gpuspin.cu b/gpu/gpuspin.cu index b096c82..970d6f2 100644 --- a/gpu/gpuspin.cu +++ b/gpu/gpuspin.cu | |||
@@ -57,7 +57,7 @@ size_t CHUNK_SIZE = 0; | |||
57 | 57 | ||
58 | int TOKEN_LOCK = -1; | 58 | int TOKEN_LOCK = -1; |
59 | 59 | ||
60 | bool USE_ENGINE_LOCKS = true; | 60 | bool USE_ENGINE_LOCKS = false; |
61 | bool USE_DYNAMIC_GROUP_LOCKS = false; | 61 | bool USE_DYNAMIC_GROUP_LOCKS = false; |
62 | int EE_LOCKS[NR_GPUS]; | 62 | int EE_LOCKS[NR_GPUS]; |
63 | int CE_SEND_LOCKS[NR_GPUS]; | 63 | int CE_SEND_LOCKS[NR_GPUS]; |
@@ -692,12 +692,13 @@ static void init_cuda(int num_gpu_users) | |||
692 | { | 692 | { |
693 | if (i != j) | 693 | if (i != j) |
694 | { | 694 | { |
695 | int other = GPU_PARTITION*GPU_PARTITION_SIZE + j; | ||
695 | int canAccess = 0; | 696 | int canAccess = 0; |
696 | cudaDeviceCanAccessPeer(&canAccess, i, j); | 697 | cudaDeviceCanAccessPeer(&canAccess, which, other); |
697 | if(canAccess) | 698 | if(canAccess) |
698 | { | 699 | { |
699 | cudaDeviceEnablePeerAccess(j, 0); | 700 | cudaDeviceEnablePeerAccess(other, 0); |
700 | p2pMigration[i][j] = true; | 701 | p2pMigration[which][other] = true; |
701 | } | 702 | } |
702 | } | 703 | } |
703 | } | 704 | } |
@@ -1294,8 +1295,8 @@ enum eScheduler | |||
1294 | RT_LINUX | 1295 | RT_LINUX |
1295 | }; | 1296 | }; |
1296 | 1297 | ||
1297 | #define CPU_OPTIONS "p:z:c:wlveio:f:s:q:X:L:Q:d" | 1298 | #define CPU_OPTIONS "p:z:c:wlveio:f:s:q:X:L:Q:d:" |
1298 | #define GPU_OPTIONS "g:y:r:C:E:DG:xS:R:T:Z:aFm:b:MNIk:" | 1299 | #define GPU_OPTIONS "g:y:r:C:E:DG:xS:R:T:Z:aFm:b:MNIk:V" |
1299 | 1300 | ||
1300 | // concat the option strings | 1301 | // concat the option strings |
1301 | #define OPTSTR CPU_OPTIONS GPU_OPTIONS | 1302 | #define OPTSTR CPU_OPTIONS GPU_OPTIONS |
@@ -1372,6 +1373,9 @@ int main(int argc, char** argv) | |||
1372 | NUM_COPY_ENGINES = atoi(optarg); | 1373 | NUM_COPY_ENGINES = atoi(optarg); |
1373 | assert(NUM_COPY_ENGINES == 1 || NUM_COPY_ENGINES == 2); | 1374 | assert(NUM_COPY_ENGINES == 1 || NUM_COPY_ENGINES == 2); |
1374 | break; | 1375 | break; |
1376 | case 'V': | ||
1377 | RESERVED_MIGR_COPY_ENGINE = true; | ||
1378 | break; | ||
1375 | case 'E': | 1379 | case 'E': |
1376 | USE_ENGINE_LOCKS = true; | 1380 | USE_ENGINE_LOCKS = true; |
1377 | ENGINE_LOCK_TYPE = (eEngineLockTypes)atoi(optarg); | 1381 | ENGINE_LOCK_TYPE = (eEngineLockTypes)atoi(optarg); |
@@ -1440,7 +1444,9 @@ int main(int argc, char** argv) | |||
1440 | want_signals = 1; | 1444 | want_signals = 1; |
1441 | break; | 1445 | break; |
1442 | case 'd': | 1446 | case 'd': |
1443 | drain = DRAIN_SOBLIV; | 1447 | drain = (budget_drain_policy_t)atoi(optarg); |
1448 | assert(drain >= DRAIN_SIMPLE && drain <= DRAIN_SOBLIV); | ||
1449 | assert(drain != DRAIN_SAWARE); // unsupported | ||
1444 | break; | 1450 | break; |
1445 | case 'l': | 1451 | case 'l': |
1446 | test_loop = 1; | 1452 | test_loop = 1; |
@@ -1623,18 +1629,6 @@ int main(int argc, char** argv) | |||
1623 | activate_litmus_signals(SIG_BUDGET_MASK, longjmp_on_litmus_signal); | 1629 | activate_litmus_signals(SIG_BUDGET_MASK, longjmp_on_litmus_signal); |
1624 | } | 1630 | } |
1625 | 1631 | ||
1626 | if (scheduler == LITMUS) | ||
1627 | { | ||
1628 | ret = task_mode(LITMUS_RT_TASK); | ||
1629 | if (ret != 0) | ||
1630 | bail_out("could not become RT task"); | ||
1631 | } | ||
1632 | else | ||
1633 | { | ||
1634 | trace_name(); | ||
1635 | trace_param(); | ||
1636 | } | ||
1637 | |||
1638 | // if (protocol >= 0) { | 1632 | // if (protocol >= 0) { |
1639 | // /* open reference to semaphore */ | 1633 | // /* open reference to semaphore */ |
1640 | // lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster); | 1634 | // lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster); |
@@ -1654,12 +1648,20 @@ int main(int argc, char** argv) | |||
1654 | 1648 | ||
1655 | init_cuda(num_gpu_users); | 1649 | init_cuda(num_gpu_users); |
1656 | safetynet = true; | 1650 | safetynet = true; |
1657 | |||
1658 | if (ENABLE_RT_AUX_THREADS) | ||
1659 | if (enable_aux_rt_tasks(AUX_CURRENT | AUX_FUTURE) != 0) | ||
1660 | bail_out("enable_aux_rt_tasks() failed"); | ||
1661 | } | 1651 | } |
1662 | 1652 | ||
1653 | if (scheduler == LITMUS) | ||
1654 | { | ||
1655 | ret = task_mode(LITMUS_RT_TASK); | ||
1656 | if (ret != 0) | ||
1657 | bail_out("could not become RT task"); | ||
1658 | } | ||
1659 | else | ||
1660 | { | ||
1661 | trace_name(); | ||
1662 | trace_param(); | ||
1663 | } | ||
1664 | |||
1663 | if (wait) { | 1665 | if (wait) { |
1664 | ret = wait_for_ts_release2(&releaseTime); | 1666 | ret = wait_for_ts_release2(&releaseTime); |
1665 | if (ret != 0) | 1667 | if (ret != 0) |
@@ -1674,6 +1676,11 @@ int main(int argc, char** argv) | |||
1674 | sleep_next_period_linux(); | 1676 | sleep_next_period_linux(); |
1675 | } | 1677 | } |
1676 | 1678 | ||
1679 | if (scheduler == LITMUS && GPU_USING && ENABLE_RT_AUX_THREADS) { | ||
1680 | if (enable_aux_rt_tasks(AUX_CURRENT | AUX_FUTURE) != 0) | ||
1681 | bail_out("enable_aux_rt_tasks() failed"); | ||
1682 | } | ||
1683 | |||
1677 | start = wctime(); | 1684 | start = wctime(); |
1678 | 1685 | ||
1679 | if (scheduler == LITMUS) | 1686 | if (scheduler == LITMUS) |
diff --git a/src/migration.c b/src/migration.c index 152d81b..7ac320e 100644 --- a/src/migration.c +++ b/src/migration.c | |||
@@ -4,8 +4,13 @@ | |||
4 | #include <sched.h> /* for cpu sets */ | 4 | #include <sched.h> /* for cpu sets */ |
5 | #include <unistd.h> | 5 | #include <unistd.h> |
6 | 6 | ||
7 | #ifdef LITMUS_NUMA_SUPPORT | ||
8 | #include <numa.h> | ||
9 | #endif | ||
10 | |||
7 | #include "migration.h" | 11 | #include "migration.h" |
8 | 12 | ||
13 | |||
9 | extern ssize_t read_file(const char* fname, void* buf, size_t maxlen); | 14 | extern ssize_t read_file(const char* fname, void* buf, size_t maxlen); |
10 | 15 | ||
11 | int release_master() | 16 | int release_master() |
@@ -54,6 +59,50 @@ int cluster_to_first_cpu(int cluster, int cluster_sz) | |||
54 | return first_cpu; | 59 | return first_cpu; |
55 | } | 60 | } |
56 | 61 | ||
62 | #ifdef LITMUS_NUMA_SUPPORT | ||
63 | /* Restrict the task to the numa nodes in the cpu mask. */ | ||
64 | /* Call this before setting up CPU affinity masks since that mask may be | ||
65 | * a subset of the numa nodes. */ | ||
66 | static int setup_numa(pid_t tid, int sz, const cpu_set_t *cpus) | ||
67 | { | ||
68 | int nr_nodes; | ||
69 | struct bitmask* new_nodes; | ||
70 | struct bitmask* old_nodes; | ||
71 | int i; | ||
72 | int ret = 0; | ||
73 | |||
74 | if (numa_available() != 0) | ||
75 | goto out; | ||
76 | |||
77 | nr_nodes = numa_max_node()+1; | ||
78 | new_nodes = numa_bitmask_alloc(nr_nodes); | ||
79 | old_nodes = numa_bitmask_alloc(nr_nodes); | ||
80 | /* map the cpu mask to a numa mask */ | ||
81 | for (i = 0; i < sz; ++i) { | ||
82 | if(CPU_ISSET_S(i, sz, cpus)) { | ||
83 | numa_bitmask_setbit(new_nodes, numa_node_of_cpu(i)); | ||
84 | } | ||
85 | } | ||
86 | /* compute the complement numa mask */ | ||
87 | for (i = 0; i < nr_nodes; ++i) { | ||
88 | if (!numa_bitmask_isbitset(new_nodes, i)) { | ||
89 | numa_bitmask_setbit(old_nodes, i); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | numa_set_strict(1); | ||
94 | numa_bind(new_nodes); /* sets CPU and memory policy */ | ||
95 | ret = numa_migrate_pages(tid, old_nodes, new_nodes); /* move over prio alloc'ed pages */ | ||
96 | numa_bitmask_free(new_nodes); | ||
97 | numa_bitmask_free(old_nodes); | ||
98 | |||
99 | out: | ||
100 | return ret; | ||
101 | } | ||
102 | #else | ||
103 | #define setup_numa(x, y, z) 0 | ||
104 | #endif | ||
105 | |||
57 | int be_migrate_thread_to_cpu(pid_t tid, int target_cpu) | 106 | int be_migrate_thread_to_cpu(pid_t tid, int target_cpu) |
58 | { | 107 | { |
59 | cpu_set_t *cpu_set; | 108 | cpu_set_t *cpu_set; |
@@ -82,7 +131,9 @@ int be_migrate_thread_to_cpu(pid_t tid, int target_cpu) | |||
82 | if (tid == 0) | 131 | if (tid == 0) |
83 | tid = gettid(); | 132 | tid = gettid(); |
84 | 133 | ||
85 | ret = sched_setaffinity(tid, sz, cpu_set); | 134 | ret = (setup_numa(tid, sz, cpu_set) >= 0) ? 0 : -1; |
135 | if (!ret) | ||
136 | ret = sched_setaffinity(tid, sz, cpu_set); | ||
86 | 137 | ||
87 | CPU_FREE(cpu_set); | 138 | CPU_FREE(cpu_set); |
88 | 139 | ||
@@ -114,7 +165,7 @@ int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, | |||
114 | } | 165 | } |
115 | 166 | ||
116 | master = (ignore_rm) ? -1 : release_master(); | 167 | master = (ignore_rm) ? -1 : release_master(); |
117 | num_cpus = num_online_cpus(); | 168 | num_cpus = num_online_cpus(); |
118 | 169 | ||
119 | if (num_cpus == -1 || last_cpu >= num_cpus || first_cpu < 0) | 170 | if (num_cpus == -1 || last_cpu >= num_cpus || first_cpu < 0) |
120 | return -1; | 171 | return -1; |
@@ -133,7 +184,9 @@ int __be_migrate_thread_to_cluster(pid_t tid, int cluster, int cluster_sz, | |||
133 | if (tid == 0) | 184 | if (tid == 0) |
134 | tid = gettid(); | 185 | tid = gettid(); |
135 | 186 | ||
136 | ret = sched_setaffinity(tid, sz, cpu_set); | 187 | ret = (setup_numa(tid, sz, cpu_set) >= 0) ? 0 : -1; |
188 | if (!ret) | ||
189 | ret = sched_setaffinity(tid, sz, cpu_set); | ||
137 | 190 | ||
138 | CPU_FREE(cpu_set); | 191 | CPU_FREE(cpu_set); |
139 | 192 | ||