source: CIVL/examples/translation/cuda/cuda-helper.cvh@ d87ec9c

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since d87ec9c was fc22fbf, checked in by Andre Marianiello <andre.marianiello@…>, 12 years ago

Fixed the ifdefs that prevent multiple header inclusion in cuda.cvh and cuda-helper.cvh

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@1281 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/* This header file contains useful helper functions for manipulating
2 * the CIVL versions of various Cuda objects.
3 */
4#ifdef __CUDA_HELPER__
5#else
6#define __CUDA_HELPER__
7
8#include "civlc.h"
9#include "cuda-types.cvh"
10#include <string.h>
11#include <stdio.h>
12
13/* Computes the one dimensional index of a grid cell at a given location
14 * in a three dimensional grid of a given size
15 */
16int _index (dim3 size, uint3 location) {
17 return location.x + size.x * (location.y + size.y * location.z);
18}
19
20/* Lifts a single integer x into a three dimensional vector representing
21 * a one dimensional grid of length x
22 */
23dim3 _toDim3(int x) {
24 dim3 d = { x, 1, 1 };
25
26 return d;
27}
28
29/* Given a three dimensional vector representing a grid of size dim,
30 * create and destroy a process, in parallel, for each cell in the grid.
31 * The location of the cell is passed to the spawning function.
32 */
33void _runProcs(dim3 dim, void spawningFunction(uint3)) {
34 $proc procs[dim.x][dim.y][dim.z];
35 for (int x = 0; x < dim.x; x++) {
36 for (int y = 0; y < dim.y; y++) {
37 for (int z = 0; z < dim.z; z++) {
38 uint3 id = { x, y, z };
39
40 procs[x][y][z] = $spawn spawningFunction(id);
41 }
42
43 }
44 }
45 for (int x = 0; x < dim.x; x++) {
46 for (int y = 0; y < dim.y; y++) {
47 for (int z = 0; z < dim.z; z++) {
48 $wait(procs[x][y][z]);
49 }
50 }
51 }
52}
53
54// ------------------------------------------------
55
56/* $wait on a given process is it is non-null
57 */
58void _tryWait($proc p) {
59 if (p != $proc_null)
60 $wait(p);
61}
62
63/* The current state of the GPU
64 */
65_cudaContext _context = {
66 .headNode = NULL,
67 .nullStream = NULL,
68 .numStreams = 0
69};
70
71/* malloc and initialize a new _kernelInstance
72 */
73_kernelInstance *_kernelInstanceCreate() {
74 //printf("mallocing kernel instance\n");
75 _kernelInstance *i = (_kernelInstance*)$malloc($root, sizeof(_kernelInstance));
76
77 i->process = $proc_null;
78 i->status = _kernelStatusWaiting;
79 return i;
80}
81
82/* cleanup and free a given _kernelInstance
83 */
84void _kernelInstanceDestroy(_kernelInstance *i) {
85 _tryWait(i->process);
86 //printf("freeing kernel instance\n");
87 $free(i);
88}
89
90/* malloc and initialize a new _kernelInstanceNode
91 */
92_kernelInstanceNode *_kernelInstanceNodeCreate() {
93 //printf("mallocing kernel instance node\n");
94 _kernelInstanceNode *node = (_kernelInstanceNode*)$malloc($root, sizeof(_kernelInstanceNode));
95
96 node->instance = NULL;
97 node->next = NULL;
98 return node;
99}
100
101/* cleanup and free a given _kernelInstanceNode
102 */
103void _kernelInstanceNodeDestroy(_kernelInstanceNode *node) {
104 _kernelInstanceDestroy(node->instance);
105 //printf("freeing kernel instance node\n");
106 $free(node);
107}
108
109/* malloc and initialize a new stream
110 */
111cudaStream_t _streamCreate() {
112 cudaStream_t s;
113
114 //printf("mallocing cuda stream\n");
115 s = (cudaStream_t)$malloc($root, sizeof(_CUstream));
116 s->mostRecent = _kernelInstanceNodeCreate();
117 s->mostRecent->instance = _kernelInstanceCreate();
118 s->mostRecent->instance->status = _kernelStatusFinished;
119 s->usable = $true;
120 return s;
121}
122
123/* block until the most recently enqueued process on the given stream
124 * has terminated (meaning all kernels in that stream have completed)
125 */
126void _streamWait(cudaStream_t s) {
127 _kernelInstance *mostRecentInstance = s->mostRecent->instance;
128
129 $when (mostRecentInstance->status == _kernelStatusFinished) ;
130}
131
132/* block until no more streams have kernels executing
133 */
134void _streamWaitAll() {
135 _cudaStreamNode *curNode = _context.headNode;
136
137 while (curNode != NULL) {
138 _streamWait(curNode->stream);
139 curNode = curNode->next;
140 }
141}
142
143/* cleanup and free a given stream
144 */
145void _streamDestroy(cudaStream_t s) {
146 _kernelInstanceNode *curNode = s->mostRecent;
147 _kernelInstanceNode *nextNode;
148
149 while (curNode != NULL) {
150 nextNode = curNode->next;
151 _kernelInstanceNodeDestroy(curNode);
152 curNode = nextNode;
153 }
154 //printf("freeing cuda stream\n");
155 $free(s);
156}
157
158/* malloc and initialize a new _cudaStreamNode
159 */
160_cudaStreamNode *_streamNodeCreate() {
161 //printf("mallocing cuda stream node\n");
162 _cudaStreamNode *node = (_cudaStreamNode*)$malloc($root, sizeof(_cudaStreamNode));
163
164 node->stream = NULL;
165 node->next = NULL;
166 return node;
167}
168
169/* cleanup and free a given _cudaStreamNode
170 */
171void _streamNodeDestroy(_cudaStreamNode *node) {
172 $assert(!node->stream->usable);
173 _streamDestroy(node->stream);
174 //printf("freeing cuda stream node\n");
175 $free(node);
176}
177
178/* destroy all stream nodes contained in the context
179 */
180void _streamNodeDestroyAll() {
181 _cudaStreamNode *curNode = _context.headNode;
182 _cudaStreamNode *nextNode;
183
184 while (curNode != NULL) {
185 nextNode = curNode->next;
186 _streamNodeDestroy(curNode);
187 curNode = nextNode;
188 }
189 _context.headNode = NULL;
190}
191
192/* malloc and initialize a new event
193 */
194cudaEvent_t _eventCreate() {
195 //printf("mallocing event\n");
196 cudaEvent_t e = (cudaEvent_t)$malloc($root, sizeof(_CUevent));
197
198 e->numInstances = 0;
199 e->instances = NULL;
200 return e;
201}
202
203/* block until all _kernelInstances contained in this event have
204 * completed
205 */
206void _eventWait(cudaEvent_t e) {
207 for (int i = 0; i < e->numInstances; i++) {
208 $when (e->instances[i]->status == _kernelStatusFinished) ;
209 }
210}
211
212/* cleanup and free a given event
213 */
214void _eventDestroy(cudaEvent_t e) {
215 if (e->instances != NULL) {
216 //printf("freeing instance list a\n");
217 $free(e->instances);
218 }
219 //printf("freeing event\n");
220 $free(e);
221}
222
223/* initialize the cuda context. must be called before any cuda functions.
224 */
225void _cudaInit() {
226 _context.nullStream = _streamCreate();
227}
228
229/* cleanup the cuda context. must be called after all cuda functions.
230 */
231void _cudaFinalize() {
232 _streamWaitAll();
233 _streamWait(_context.nullStream);
234 _streamNodeDestroyAll();
235 _streamDestroy(_context.nullStream);
236}
237
238/* returns an array of pointers to the most recently enqueued kernel
239 * of each stream.
240 */
241_kernelInstance **_allMostRecentKernels() {
242 int n = _context.numStreams + 1;
243 _cudaStreamNode *curNode = _context.headNode;
244 //printf("mallocing instance list a\n");
245 _kernelInstance **insts = (_kernelInstance**)$malloc($root, n * sizeof(_kernelInstance*)) ;
246
247 insts[0] = _context.nullStream->mostRecent->instance;
248 for (int i = 1; i < n; i++, curNode = curNode->next) {
249 insts[i] = curNode->stream->mostRecent->instance;
250 }
251 return insts;
252}
253
254/* create a kernel instance for the given function k, and enqueue it
255 * onto the given stream.
256 */
257void _enqueueKernel(cudaStream_t stream, void (*k)(_kernelInstance*, cudaEvent_t)) {
258 cudaStream_t s;
259 cudaEvent_t e = _eventCreate();
260 _kernelInstanceNode *newNode = _kernelInstanceNodeCreate();
261
262 if (stream == NULL) {
263 e->numInstances = _context.numStreams + 1;
264 e->instances = _allMostRecentKernels();
265 s = _context.nullStream;
266 } else {
267 e->numInstances = 2;
268 //printf("mallocing instance list b\n");
269 e->instances = (_kernelInstance**)$malloc($root, 2 * sizeof(_kernelInstance*)) ;
270 e->instances[0] = stream->mostRecent->instance;
271 e->instances[1] = _context.nullStream->mostRecent->instance;
272 s = stream;
273 }
274 $assert(s->usable);
275 newNode->instance = _kernelInstanceCreate();
276 newNode->next = s->mostRecent;
277 s->mostRecent = newNode;
278 s->mostRecent->instance->process = $spawn k(s->mostRecent->instance, e);
279}
280
281/* called by kernel processes. wait on the given event, then update
282 * the status of the calling kernel to indicate it has finished waiting
283 */
284void _waitInQueue (_kernelInstance *this, cudaEvent_t e) {
285 _eventWait(e);
286 _eventDestroy(e);
287 this->status = _kernelStatusRunning;
288}
289
290/* called by kernel processes. update the status of the calling kernel
291 * to indicate that it has completed execution
292 */
293void _kernelFinish(_kernelInstance *k) {
294 k->status = _kernelStatusFinished;
295}
296
297#endif
Note: See TracBrowser for help on using the repository browser.