diff --git a/configure.ac b/configure.ac index 5964256..8ea669b 100755 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_SUBST(MAJOR_VERSION) AC_SUBST(MINOR_VERSION) -AC_ARG_VAR(CUDA_H_PATH, help-string) +AC_ARG_VAR(CUDA_H_PATH, path to CUDA Toolkit include directory (enables CUDA support)) AC_ARG_VAR(RANLIB, ranlib tool) AC_ARG_ENABLE([verbs_exp], @@ -201,7 +201,7 @@ fi if [test "$CUDA_H_PATH" ]; then AC_DEFINE([HAVE_CUDA], [1], [Enable CUDA feature]) - AC_DEFINE_UNQUOTED([CUDA_PATH], "$CUDA_H_PATH" , [Enable CUDA feature]) + AC_DEFINE_UNQUOTED([CUDA_PATH], "$CUDA_H_PATH" , [Path to CUDA toolkit include directory]) LIBS=$LIBS" -lcuda" fi diff --git a/src/perftest_parameters.c b/src/perftest_parameters.c index a21b6eb..4cc3222 100755 --- a/src/perftest_parameters.c +++ b/src/perftest_parameters.c @@ -433,6 +433,8 @@ static void usage(const char *argv0, VerbType verb, TestType tst, int connection #ifdef HAVE_CUDA printf(" --use_cuda "); printf(" Use CUDA lib for GPU-Direct testing.\n"); + printf(" --use_cuda_um "); + printf(" Use CUDA Unified Memory for GPU-Direct testing, needs --use_cuda.\n"); #endif @@ -603,7 +605,10 @@ static void init_perftest_params(struct perftest_parameters *user_param) user_param->rate_limit_type = DISABLE_RATE_LIMIT; user_param->is_rate_limit_type = 0; user_param->output = -1; + #ifdef HAVE_CUDA user_param->use_cuda = 0; + user_param->use_cuda_um = 0; + #endif user_param->mmap_file = NULL; user_param->mmap_offset = 0; user_param->iters_per_port[0] = 0; @@ -1036,6 +1041,10 @@ static void force_dependecies(struct perftest_parameters *user_param) } } + if (user_param->use_odp) { + fprintf(stdout," ODP enabled\n"); + } + if(user_param->verb == ATOMIC && user_param->use_odp) { printf(RESULT_LINE); fprintf(stderr," ODP does not support ATOMICS for now\n"); @@ -1187,19 +1196,17 @@ static void force_dependecies(struct perftest_parameters *user_param) #endif #ifdef HAVE_CUDA - if (user_param->use_cuda) { - if (user_param->tst != BW) { - printf(RESULT_LINE); - fprintf(stderr," Perftest supports CUDA only in BW tests\n"); - exit(1); - } - } - if (user_param->use_cuda && user_param->mmap_file != NULL) { printf(RESULT_LINE); fprintf(stderr,"You cannot use CUDA and an mmap'd file at the same time\n"); exit(1); } + + if (user_param->use_cuda_um && !user_param->use_cuda) { + printf(RESULT_LINE); + fprintf(stderr," Need to enable CUDA support for CUDA Managed Memory\n"); + exit(1); + } #endif if ( (user_param->connection_type == UD) && (user_param->inline_size > MAX_INLINE_UD) ) { @@ -1490,19 +1497,20 @@ static void ctx_set_max_inline(struct ibv_context *context,struct perftest_param } if (user_param->inline_size == DEF_INLINE) { - - if (user_param->tst ==LAT) { + user_param->inline_size = 0; + if (user_param->tst == LAT + #ifdef HAVE_CUDA + && user_param->use_cuda == 0 + #endif + ) { switch(user_param->verb) { - case WRITE: user_param->inline_size = (user_param->connection_type == DC)? DEF_INLINE_DC : DEF_INLINE_WRITE; break; case SEND : user_param->inline_size = (user_param->connection_type == DC)? DEF_INLINE_DC : (user_param->connection_type == UD)? DEF_INLINE_SEND_UD : ((user_param->connection_type == XRC) ? DEF_INLINE_SEND_XRC : DEF_INLINE_SEND_RC_UC) ; break; default : user_param->inline_size = 0; } - } else { - user_param->inline_size = 0; } } @@ -1534,7 +1542,10 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc) static int retry_count_flag = 0; static int dont_xchg_versions_flag = 0; static int use_exp_flag = 0; + #ifdef HAVE_CUDA static int use_cuda_flag = 0; + static int use_cuda_um_flag = 0; + #endif static int mmap_file_flag = 0; static int mmap_offset_flag = 0; static int ipv6_flag = 0; @@ -1630,7 +1641,10 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc) { .name = "flow_label", .has_arg = 1, .flag = &flow_label_flag, .val = 1}, { .name = "retry_count", .has_arg = 1, .flag = &retry_count_flag, .val = 1}, { .name = "dont_xchg_versions", .has_arg = 0, .flag = &dont_xchg_versions_flag, .val = 1}, + #ifdef HAVE_CUDA { .name = "use_cuda", .has_arg = 0, .flag = &use_cuda_flag, .val = 1}, + { .name = "use_cuda_um", .has_arg = 0, .flag = &use_cuda_um_flag, .val = 1}, + #endif { .name = "mmap", .has_arg = 1, .flag = &mmap_file_flag, .val = 1}, { .name = "mmap-offset", .has_arg = 1, .flag = &mmap_offset_flag, .val = 1}, { .name = "ipv6", .has_arg = 0, .flag = &ipv6_flag, .val = 1}, @@ -2051,10 +2065,14 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc) if (use_res_domain_flag) { user_param->use_res_domain = 1; } - + #ifdef HAVE_CUDA if (use_cuda_flag) { user_param->use_cuda = 1; } + if (use_cuda_um_flag) { + user_param->use_cuda_um = 1; + } + #endif if (report_both_flag) { user_param->report_both = 1; } diff --git a/src/perftest_parameters.h b/src/perftest_parameters.h index 448e398..cbefcee 100755 --- a/src/perftest_parameters.h +++ b/src/perftest_parameters.h @@ -389,7 +389,10 @@ struct perftest_parameters { int buff_size; int pkey_index; int raw_qos; + #ifdef HAVE_CUDA int use_cuda; + int use_cuda_um; + #endif char *mmap_file; unsigned long mmap_offset; /* New test params format pilot. will be used in all flags soon,. */ diff --git a/src/perftest_resources.c b/src/perftest_resources.c index afae5f2..13d31ca 100755 --- a/src/perftest_resources.c +++ b/src/perftest_resources.c @@ -53,7 +53,7 @@ struct check_alive_data check_alive_data; static CUdevice cuDevice; static CUcontext cuContext; -static int pp_init_gpu(struct pingpong_context *ctx, size_t _size) +static int pp_init_gpu(struct pingpong_context *ctx, size_t _size, int use_um) { const size_t gpu_page_size = 64*1024; size_t size = (_size + gpu_page_size - 1) & ~(gpu_page_size - 1); @@ -79,15 +79,19 @@ static int pp_init_gpu(struct pingpong_context *ctx, size_t _size) else printf("There are %d devices supporting CUDA, picking first...\n", deviceCount); - int devID = 0; + int gpuID = 0; - /* pick up device with zero ordinal (default, or devID) */ - CUCHECK(cuDeviceGet(&cuDevice, devID)); + /* pick up device with zero ordinal (default, or gpuID) */ + CUCHECK(cuDeviceGet(&cuDevice, gpuID)); char name[128]; - CUCHECK(cuDeviceGetName(name, sizeof(name), devID)); - printf("[pid = %d, dev = %d] device name = [%s]\n", getpid(), cuDevice, name); - printf("creating CUDA Ctx\n"); + int pciDomainID, pciBusID, pciDeviceID; + CUCHECK(cuDeviceGetName(name, sizeof(name), cuDevice)); + CUCHECK(cuDeviceGetAttribute(&pciDomainID, CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, cuDevice)); + CUCHECK(cuDeviceGetAttribute(&pciBusID, CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, cuDevice)); + CUCHECK(cuDeviceGetAttribute(&pciDeviceID, CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, cuDevice)); + printf("[pid=%d id=%d dev=%d] GPU name=[%s] PCI Domain/Bus/Dev: %04x/%02x/%02x\n", + getpid(), gpuID, cuDevice, name, pciDomainID, pciBusID, pciDeviceID); /* Create context */ error = cuCtxCreate(&cuContext, CU_CTX_MAP_HOST, cuDevice); @@ -104,17 +108,21 @@ static int pp_init_gpu(struct pingpong_context *ctx, size_t _size) } printf("cuMemAlloc() of a %zd bytes GPU buffer\n", size); - CUdeviceptr d_A; - error = cuMemAlloc(&d_A, size); - if (error != CUDA_SUCCESS) { - printf("cuMemAlloc error=%d\n", error); - return 1; - } - printf("allocated GPU buffer address at %016llx pointer=%p\n", d_A, - (void *) d_A); - ctx->buf[0] = (void*)d_A; - - return 0; + CUdeviceptr d_A; + if (use_um) { + error = cuMemAllocManaged(&d_A, size, CU_MEM_ATTACH_GLOBAL); + } else { + error = cuMemAlloc(&d_A, size); + } + if (error != CUDA_SUCCESS) { + printf("CUDA allocation failed with error=%d\n", error); + ctx->buf[0] = NULL; + return 1; + } + printf("allocated GPU buffer address at %016llx\n", d_A); + ctx->buf[0] = (void*)d_A; + + return 0; } static int pp_free_gpu(struct pingpong_context *ctx) @@ -123,7 +131,7 @@ static int pp_free_gpu(struct pingpong_context *ctx) CUdeviceptr d_A = (CUdeviceptr) ctx->buf[0]; printf("deallocating RX GPU buffer\n"); - cuMemFree(d_A); + CUCHECK(cuMemFree(d_A)); d_A = 0; printf("destroying current CUDA Ctx\n"); @@ -1157,7 +1165,7 @@ int create_single_mr(struct pingpong_context *ctx, struct perftest_parameters *u #ifdef HAVE_CUDA if (user_param->use_cuda) { ctx->is_contig_supported = FAILURE; - if(pp_init_gpu(ctx, ctx->buff_size)) { + if(pp_init_gpu(ctx, ctx->buff_size, user_param->use_cuda_um)) { fprintf(stderr, "Couldn't allocate work buf.\n"); return 1; } @@ -1251,6 +1259,10 @@ int create_single_mr(struct pingpong_context *ctx, struct perftest_parameters *u /* Initialize buffer with random numbers */ srand(time(NULL)); + #ifdef HAVE_CUDA + // CUDA memory pointers cannot be de-referenced on CPU code + if (!user_param->use_cuda) + #endif for (i = 0; i < ctx->buff_size; i++) { ((char*)ctx->buf[qp_index])[i] = (char)rand(); } @@ -1338,10 +1350,12 @@ int ctx_init(struct pingpong_context *ctx, struct perftest_parameters *user_para if (create_mr(ctx, user_param)) { fprintf(stderr, "Failed to create MR\n"); + return FAILURE; } if (create_cqs(ctx, user_param)) { fprintf(stderr, "Failed to create CQs\n"); + return FAILURE; } #ifdef HAVE_XRCD