xref: /libCEED/backends/cuda-gen/ceed-cuda-gen-qfunction.c (revision fe7bf0e48e9eb8400f8e623b22fb8917195d5929)
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-backend.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include "../cuda/ceed-cuda.h"
21 #include "ceed-cuda-gen.h"
22 
23 //------------------------------------------------------------------------------
24 // Apply QFunction
25 //------------------------------------------------------------------------------
26 static int CeedQFunctionApply_Cuda_gen(CeedQFunction qf, CeedInt Q,
27                                        CeedVector *U, CeedVector *V) {
28   int ierr;
29   Ceed ceed;
30   ierr = CeedQFunctionGetCeed(qf, &ceed); CeedChk(ierr);
31   return CeedError(ceed, 1, "Backend does not implement QFunctionApply");
32 }
33 
34 //------------------------------------------------------------------------------
35 // Destroy QFunction
36 //------------------------------------------------------------------------------
37 static int CeedQFunctionDestroy_Cuda_gen(CeedQFunction qf) {
38   int ierr;
39   CeedQFunction_Cuda_gen *data;
40   ierr = CeedQFunctionGetData(qf, (void *)&data); CeedChk(ierr);
41   Ceed ceed;
42   ierr = CeedQFunctionGetCeed(qf, &ceed); CeedChk(ierr);
43   ierr = cudaFree(data->d_c); CeedChk_Cu(ceed, ierr);
44   ierr = CeedFree(&data); CeedChk(ierr);
45   return 0;
46 }
47 
48 //------------------------------------------------------------------------------
49 // Load QFunction
50 //------------------------------------------------------------------------------
51 static int loadCudaFunction(CeedQFunction qf, char *c_src_file) {
52   int ierr;
53   Ceed ceed;
54   CeedQFunctionGetCeed(qf, &ceed);
55 
56   // Find source file
57   char *cuda_file;
58   ierr = CeedCalloc(CUDA_MAX_PATH, &cuda_file); CeedChk(ierr);
59   memcpy(cuda_file, c_src_file, strlen(c_src_file));
60   const char *last_dot = strrchr(cuda_file, '.');
61   if (!last_dot)
62     return CeedError(ceed, 1, "Cannot find file's extension!");
63   const size_t cuda_path_len = last_dot - cuda_file;
64   strcpy(&cuda_file[cuda_path_len], ".h");
65 
66   // Open source file
67   FILE *fp;
68   long lSize;
69   char *buffer;
70   fp = fopen ( cuda_file, "rb" );
71   if (!fp)
72     CeedError(ceed, 1, "Couldn't open the Cuda file for the QFunction.");
73 
74   // Compute size of source file
75   fseek( fp, 0L, SEEK_END);
76   lSize = ftell( fp );
77   rewind( fp );
78 
79   // Allocate memory for entire content
80   ierr = CeedCalloc( lSize+1, &buffer ); CeedChk(ierr);
81 
82   // Copy the file into the buffer
83   if (1 != fread( buffer, lSize, 1, fp) ) {
84     fclose(fp);
85     CeedFree(&buffer);
86     CeedError(ceed, 1, "Couldn't read the Cuda file for the QFunction.");
87   }
88 
89   // Append typedef and save source string
90   // FIXME: the magic number 16 should be defined somewhere...
91   char *fields_string =
92     "typedef struct { const CeedScalar* inputs[16]; CeedScalar* outputs[16]; } Fields_Cuda_gen;";
93   char *source = (char *) malloc(1 + strlen(fields_string)+ strlen(buffer) );
94   strcpy(source, fields_string);
95   strcat(source, buffer);
96   CeedQFunction_Cuda_gen *data;
97   ierr = CeedQFunctionGetData(qf, (void *)&data); CeedChk(ierr);
98   data->qFunctionSource = buffer;
99 
100 
101   fclose(fp);
102   return 0;
103 }
104 
105 //------------------------------------------------------------------------------
106 // Create QFunction
107 //------------------------------------------------------------------------------
108 int CeedQFunctionCreate_Cuda_gen(CeedQFunction qf) {
109   int ierr;
110   Ceed ceed;
111   CeedQFunctionGetCeed(qf, &ceed);
112   CeedQFunction_Cuda_gen *data;
113   ierr = CeedCalloc(1,&data); CeedChk(ierr);
114   ierr = CeedQFunctionSetData(qf, (void *)&data); CeedChk(ierr);
115   size_t ctxsize;
116   ierr = CeedQFunctionGetContextSize(qf, &ctxsize); CeedChk(ierr);
117   ierr = cudaMalloc(&data->d_c, ctxsize); CeedChk_Cu(ceed, ierr);
118 
119   char *source;
120   ierr = CeedQFunctionGetSourcePath(qf, &source); CeedChk(ierr);
121   const char *funname = strrchr(source, ':') + 1;
122   data->qFunctionName = (char *)funname;
123   const int filenamelen = funname - source;
124   char filename[filenamelen];
125   memcpy(filename, source, filenamelen - 1);
126   filename[filenamelen - 1] = '\0';
127   ierr = loadCudaFunction(qf, filename); CeedChk(ierr);
128 
129   ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Apply",
130                                 CeedQFunctionApply_Cuda_gen); CeedChk(ierr);
131   ierr = CeedSetBackendFunction(ceed, "QFunction", qf, "Destroy",
132                                 CeedQFunctionDestroy_Cuda_gen); CeedChk(ierr);
133   return 0;
134 }
135 //------------------------------------------------------------------------------
136