summaryrefslogtreecommitdiffstats
path: root/copy_experiments
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-06-21 11:36:12 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-06-21 11:36:12 -0400
commit938c9c08d726485231bd86ba1389599732a61658 (patch)
treefcdf45f02add9071f181e96e0ed8edb634ce2a72 /copy_experiments
parentd82c60cbfb35697b1dbd579eccc35e0d7902e453 (diff)
Rewrite argument parsing for mon_cross_ctx_copies
No longer requires a recompile to change the number or type of copy monitoring threads.
Diffstat (limited to 'copy_experiments')
-rw-r--r--copy_experiments/mon_cross_ctx_copies.cu93
1 files changed, 65 insertions, 28 deletions
diff --git a/copy_experiments/mon_cross_ctx_copies.cu b/copy_experiments/mon_cross_ctx_copies.cu
index b38d037..65ccd4e 100644
--- a/copy_experiments/mon_cross_ctx_copies.cu
+++ b/copy_experiments/mon_cross_ctx_copies.cu
@@ -13,6 +13,22 @@
13#include <unistd.h> 13#include <unistd.h>
14#include <cuda.h> 14#include <cuda.h>
15#include <pthread.h> 15#include <pthread.h>
16#include <argp.h>
17
18// Data for the help text(s)
19const char* maintainer = "<jbakita@cs.unc.edu>";
20const char* version = "mon_cross_ctx_copies 2023.06";
21const char* desc =
22 "Copy data to, from, or between GPU(s) and log the time that each block "
23 "of the copy completes. Data need not be transferred sequentially for "
24 "transfer times to be properly recorded.";
25
26const struct argp_option opts[] = {
27 {"copy_size", 's', "NUM_PAGES", 0, "Number of 4KiB pages to copy"},
28 {"gpu", 'g', /*"DIRECTION"*/0, 0, "Add a GPU-monitored copy thread (can be duplicated)"},
29 {"cpu", 'c', /*"DIRECTION"*/0, 0, "Add a CPU-monitored copy thread (can be duplicated)"},
30 {0}
31};
16 32
17// CPU-only monitoring can only go a fraction of the speed of GPU monitoring. 33// CPU-only monitoring can only go a fraction of the speed of GPU monitoring.
18// This sets how much slower it should go. 34// This sets how much slower it should go.
@@ -47,7 +63,7 @@ typedef enum {
47} my_config_t; 63} my_config_t;
48 64
49typedef struct { 65typedef struct {
50 int *cond_var; 66 int is_ready;
51 my_config_t config; 67 my_config_t config;
52} copy_thread_args_t; 68} copy_thread_args_t;
53 69
@@ -127,7 +143,7 @@ void* copy_thread(void* args_raw) {
127 } 143 }
128 144
129 // Tell our parent we're ready 145 // Tell our parent we're ready
130 *args->cond_var = 1; 146 args->is_ready = 1;
131 // Wait for our parent to tell us to go 147 // Wait for our parent to tell us to go
132 while (!READY) 148 while (!READY)
133 continue; 149 continue;
@@ -193,29 +209,42 @@ void* copy_thread(void* args_raw) {
193 return times; 209 return times;
194} 210}
195 211
212const int MAX_THREADS = 32;
213
214typedef struct {
215 int num_threads;
216 copy_thread_args_t thread_args[MAX_THREADS];
217} global_args_t;
218
219static error_t arg_parser(int key, char* arg, struct argp_state *state) {
220 global_args_t* g_args = (global_args_t*)state->input;
221 switch (key) {
222 case 's':
223 if (atol(arg) < CPU_MON_DIVISOR * 2)
224 argp_error(state, "Please specify a larger copy size. It must be at least %d pages for accurate tracking.\n", CPU_MON_DIVISOR * 2);
225 COPY_SIZE = atol(arg) * PG_SZ;
226 break;
227 case 'g':
228 if (g_args->num_threads == MAX_THREADS)
229 argp_error(state, "Please specify less than %d monitoring threads, or increase the compiled in MAX_THREADS constraint.\n", MAX_THREADS);
230 g_args->thread_args[g_args->num_threads++] = {0, GPU_MONITORING};
231 break;
232 case 'c':
233 if (g_args->num_threads == MAX_THREADS)
234 argp_error(state, "Please specify less than %d monitoring threads, or increase the compiled in MAX_THREADS constraint.\n", MAX_THREADS);
235 g_args->thread_args[g_args->num_threads++] = {0, CPU_MONITORING};
236 break;
237 default:
238 return ARGP_ERR_UNKNOWN;
239 }
240 return 0;
241}
242
196int main(int argc, char**argv) { 243int main(int argc, char**argv) {
197 int tmp, dev; 244 int tmp, dev;
198 const int NUM_THREADS = 4; 245 uint64_t *ctx_times[MAX_THREADS] = {0};
199 pthread_t t[NUM_THREADS]; 246 pthread_t t[MAX_THREADS];
200 int is_thread_ready[NUM_THREADS] = {0}; 247 global_args_t g_args = {0};
201 uint64_t *ctx_times[NUM_THREADS] = {0};
202 // Setup thread condition variables and configuration (my_config_t enum)
203 copy_thread_args_t thread_args[NUM_THREADS] = {
204 {&is_thread_ready[0], CPU_MONITORING},
205 {&is_thread_ready[1], CPU_MONITORING},
206 {&is_thread_ready[2], CPU_MONITORING},
207 {&is_thread_ready[3], CPU_MONITORING},
208 };//, {&is_thread_ready[1], GPU_MONITORING}};//, {&is_thread_ready[2], CPU_MONITORING}, {&is_thread_ready[3], CPU_MONITORING}, {&is_thread_ready[4], CPU_MONITORING}, {&is_thread_ready[5], CPU_MONITORING}, {&is_thread_ready[6], CPU_MONITORING}, {&is_thread_ready[7], CPU_MONITORING}, {&is_thread_ready[8], CPU_MONITORING}};
209
210 if (argc != 2) {
211 fprintf(stderr, "Usage: %s <# of 4KB pages to copy to GPU>\n", argv[0]);
212 return 1;
213 }
214 if (atol(argv[1]) < CPU_MON_DIVISOR * 2) {
215 fprintf(stderr, "Please specify a larger copy size. It must be at least %d pages for accurate tracking.\n", CPU_MON_DIVISOR * 2);
216 return 2;
217 }
218 COPY_SIZE = atol(argv[1]) * PG_SZ;
219 248
220 // Due to some laziness in how we handle barriers, this flag needs to be true 249 // Due to some laziness in how we handle barriers, this flag needs to be true
221 /// XXX: Still seems to work fine if it isn't??? 250 /// XXX: Still seems to work fine if it isn't???
@@ -226,6 +255,14 @@ int main(int argc, char**argv) {
226 exit(1); 255 exit(1);
227 }*/ 256 }*/
228 257
258 struct argp argp = {opts, arg_parser, 0, desc};
259 argp_parse(&argp, argc, argv, 0, 0, &g_args);
260
261 if (g_args.num_threads == 0) {
262 fprintf(stderr, "At least one copy thread must be specified with --gpu or --cpu arguments.\n");
263 return 3;
264 }
265
229 // TODO: Rewrite this so that it's all (u)int64_t 266 // TODO: Rewrite this so that it's all (u)int64_t
230 // Skip, as this is 1-to-1 on GV100 and GV11B 267 // Skip, as this is 1-to-1 on GV100 and GV11B
231 //double d2h_scale = GetGPUTimerScale(dev); 268 //double d2h_scale = GetGPUTimerScale(dev);
@@ -237,21 +274,21 @@ int main(int argc, char**argv) {
237 274
238 srand(0); 275 srand(0);
239 // Spawn and wait for children to intialize 276 // Spawn and wait for children to intialize
240 for (int tid = 0; tid < NUM_THREADS; tid++) { 277 for (int tid = 0; tid < g_args.num_threads; tid++) {
241 pthread_create(&t[tid], NULL, copy_thread, &thread_args[tid]); 278 pthread_create(&t[tid], NULL, copy_thread, &g_args.thread_args[tid]);
242 while (!is_thread_ready[tid]) 279 while (!g_args.thread_args[tid].is_ready)
243 continue; 280 continue;
244 } 281 }
245 // Tell children initialization is done and that they can go 282 // Tell children initialization is done and that they can go
246 READY = 1; 283 READY = 1;
247 // Wait for threads to finish, and determine the earliest recorded time 284 // Wait for threads to finish, and determine the earliest recorded time
248 uint64_t smallest = UINT64_MAX; 285 uint64_t smallest = UINT64_MAX;
249 for (int tid = 0; tid < NUM_THREADS; tid++) { 286 for (int tid = 0; tid < g_args.num_threads; tid++) {
250 pthread_join(t[tid], (void**)&ctx_times[tid]); 287 pthread_join(t[tid], (void**)&ctx_times[tid]);
251 smallest = min(smallest, ctx_times[tid][0]); 288 smallest = min(smallest, ctx_times[tid][0]);
252 } 289 }
253 // Rebase times to 0 and print 290 // Rebase times to 0 and print
254 for (int tid = 0; tid < NUM_THREADS; tid++) { 291 for (int tid = 0; tid < g_args.num_threads; tid++) {
255 // Summary to stderr 292 // Summary to stderr
256 fprintf(stderr, "%lu, %lu\n", ctx_times[tid][0] - smallest, ctx_times[tid][COPY_SIZE / PG_SZ - 1] - smallest); 293 fprintf(stderr, "%lu, %lu\n", ctx_times[tid][0] - smallest, ctx_times[tid][COPY_SIZE / PG_SZ - 1] - smallest);
257 // Full dataset to stdout 294 // Full dataset to stdout