1 // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. 2 // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 3 // All Rights reserved. See files LICENSE and NOTICE for details. 4 // 5 // This file is part of CEED, a collection of benchmarks, miniapps, software 6 // libraries and APIs for efficient high-order finite element and spectral 7 // element discretizations for exascale applications. For more information and 8 // source code availability see http://github.com/ceed. 9 // 10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11 // a collaborative effort of two U.S. Department of Energy organizations (Office 12 // of Science and the National Nuclear Security Administration) responsible for 13 // the planning and preparation of a capable exascale ecosystem, including 14 // software, applications, hardware, advanced system engineering and early 15 // testbed platforms, in support of the nation's exascale computing imperative. 16 17 #include <ceed/ceed.h> 18 #include <ceed/backend.h> 19 #include <cuda.h> 20 #include <stdio.h> 21 #include <string.h> 22 #include "ceed-cuda-ref.h" 23 #include "ceed-cuda-ref-qfunction-load.h" 24 #include "../cuda/ceed-cuda-compile.h" 25 26 //------------------------------------------------------------------------------ 27 // Apply QFunction 28 //------------------------------------------------------------------------------ 29 static int CeedQFunctionApply_Cuda(CeedQFunction qf, CeedInt Q, 30 CeedVector *U, CeedVector *V) { 31 int ierr; 32 Ceed ceed; 33 ierr = CeedQFunctionGetCeed(qf, &ceed); CeedChkBackend(ierr); 34 35 // Build and compile kernel, if not done 36 ierr = CeedCudaBuildQFunction(qf); CeedChkBackend(ierr); 37 38 CeedQFunction_Cuda *data; 39 ierr = CeedQFunctionGetData(qf, &data); CeedChkBackend(ierr); 40 Ceed_Cuda *ceed_Cuda; 41 ierr = CeedGetData(ceed, &ceed_Cuda); CeedChkBackend(ierr); 42 CeedInt num_input_fields, num_output_fields; 43 ierr = CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 44 CeedChkBackend(ierr); 45 46 // Read vectors 47 for (CeedInt i = 0; i < num_input_fields; i++) { 48 ierr = CeedVectorGetArrayRead(U[i], CEED_MEM_DEVICE, &data->fields.inputs[i]); 49 CeedChkBackend(ierr); 50 } 51 for (CeedInt i = 0; i < num_output_fields; i++) { 52 ierr = CeedVectorGetArrayWrite(V[i], CEED_MEM_DEVICE, &data->fields.outputs[i]); 53 CeedChkBackend(ierr); 54 } 55 56 // Get context data 57 ierr = CeedQFunctionGetInnerContextData(qf, CEED_MEM_DEVICE, &data->d_c); 58 CeedChkBackend(ierr); 59 60 // Run kernel 61 void *args[] = {&data->d_c, (void *) &Q, &data->fields}; 62 ierr = CeedRunKernelAutoblockCuda(ceed, data->QFunction, Q, args); 63 CeedChkBackend(ierr); 64 65 // Restore vectors 66 for (CeedInt i = 0; i < num_input_fields; i++) { 67 ierr = CeedVectorRestoreArrayRead(U[i], &data->fields.inputs[i]); 68 CeedChkBackend(ierr); 69 } 70 for (CeedInt i = 0; i < num_output_fields; i++) { 71 ierr = CeedVectorRestoreArray(V[i], &data->fields.outputs[i]); 72 CeedChkBackend(ierr); 73 } 74 75 // Restore context 76 ierr = CeedQFunctionRestoreInnerContextData(qf, &data->d_c); 77 CeedChkBackend(ierr); 78 79 return CEED_ERROR_SUCCESS; 80 } 81 82 //------------------------------------------------------------------------------ 83 // Destroy QFunction 84 //------------------------------------------------------------------------------ 85 static int CeedQFunctionDestroy_Cuda(CeedQFunction qf) { 86 int ierr; 87 CeedQFunction_Cuda *data; 88 ierr = CeedQFunctionGetData(qf, &data); CeedChkBackend(ierr); 89 Ceed ceed; 90 ierr = CeedQFunctionGetCeed(qf, &ceed); CeedChkBackend(ierr); 91 if (data->module) 92 CeedChk_Cu(ceed, cuModuleUnload(data->module)); 93 ierr = CeedFree(&data); CeedChkBackend(ierr); 94 95 return CEED_ERROR_SUCCESS; 96 } 97 98 //------------------------------------------------------------------------------ 99 // Set User QFunction 100 //------------------------------------------------------------------------------ 101 static int CeedQFunctionSetCUDAUserFunction_Cuda(CeedQFunction qf, 102 CUfunction f) { 103 int ierr; 104 CeedQFunction_Cuda *data; 105 ierr = CeedQFunctionGetData(qf, &data); CeedChkBackend(ierr); 106 data->QFunction = f; 107 108 return CEED_ERROR_SUCCESS; 109 } 110 111 //------------------------------------------------------------------------------ 112 // Create QFunction 113 //------------------------------------------------------------------------------ 114 int CeedQFunctionCreate_Cuda(CeedQFunction qf) { 115 int ierr; 116 Ceed ceed; 117 CeedQFunctionGetCeed(qf, &ceed); 118 CeedQFunction_Cuda *data; 119 ierr = CeedCalloc(1, &data); CeedChkBackend(ierr); 120 ierr = CeedQFunctionSetData(qf, data); CeedChkBackend(ierr); 121 122 // Read QFunction source 123 ierr = CeedQFunctionGetKernelName(qf, &data->qfunction_name); 124 CeedChkBackend(ierr); 125 CeedDebug256(ceed, 2, "----- Loading QFunction User Source -----\n"); 126 ierr = CeedQFunctionLoadSourceToBuffer(qf, &data->qfunction_source); 127 CeedChkBackend(ierr); 128 CeedDebug256(ceed, 2, "----- Loading QFunction User Source Complete! -----\n"); 129 130 // Register backend functions 131 ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", 132 CeedQFunctionApply_Cuda); CeedChkBackend(ierr); 133 ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Destroy", 134 CeedQFunctionDestroy_Cuda); CeedChkBackend(ierr); 135 ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "SetCUDAUserFunction", 136 CeedQFunctionSetCUDAUserFunction_Cuda); 137 CeedChkBackend(ierr); 138 return CEED_ERROR_SUCCESS; 139 } 140 //------------------------------------------------------------------------------ 141