source: CIVL/examples/cuda/newCudaMockup.cvl@ 109d05e

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 109d05e was 109d05e, checked in by Alex Wilton <awilton@…>, 4 years ago

Added cuda mockup file

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

  • Property mode set to 100644
File size: 8.0 KB
Line 
1enum cudaError {
2 cudaSuccess
3};
4typedef enum cudaError cudaError_t;
5
6typedef enum cudaMemcpyKind {
7 cudaMemcpyHostToHost,
8 cudaMemcpyHostToDevice,
9 cudaMemcpyDeviceToHost,
10 cudaMemcpyDeviceToDevice,
11 cudaMemcpyDefault
12} cudaMemcpyKind;
13
14typedef struct $cuda_op {
15 _Bool start;
16 _Bool finished;
17 _Bool deleteWhenFin;
18}* $cuda_op_t;
19
20typdef struct $cuda_op_node {
21 $cuda_op_t op;
22 $cuda_op_node_t next;
23}* $cuda_op_node_t;
24
25typedef struct cudaStream {
26 $cuda_op_node_t head;
27 $cuda_op_node_t tail;
28 int numOps;
29
30 $cuda_stream_node_t containingNode;
31 _Bool alive;
32}* cudaStream_t;
33cudaStream_t $cuda_default_stream;
34
35$input int $CUDA_HEAP_OFFSET;
36
37typedef struct $cuda_stream_node {
38 $cuda_stream_t stream;
39 $cuda_stream_node_t prev;
40 $cuda_stream_node_t next;
41}* $cuda_stream_node_t;
42
43typedef struct $cuda_context {
44 $cuda_stream_node_t head;
45 int numStreams;
46} $cuda_context;
47$cuda_context $cuda_global_context;
48
49void $cuda_op_wait_start($cuda_op_t cuda_op) {
50 $unidirectional_when(cuda_op->start);
51}
52void $cuda_op_finish($cuda_op_t cuda_op) {
53 $unidirectional_when(cuda_op->finished) free(cuda_op);
54}
55
56// Helper function to get the default stream if passed NULL, and just returns stream otherwise
57cudaStream_t $default_stream_if_null(cudaStream_t stream) {
58 return stream == NULL ? $cuda_default_stream : stream;
59}
60
61$cuda_stream_node_t $create_new_stream_node() {
62 cudaStream_t newStream = (cudaStream_t) malloc(sizeof(struct cudaStream));
63 newStream->head = NULL;
64 newStream->tail = NULL;
65 newStream->numOps = 0;
66 newStream->alive = true;
67
68 $cuda_stream_node_t newHead = ($cuda_stream_node_t) malloc(sizeof(struct $cuda_stream_node));
69 newHead->stream = newStream;
70 newStream->containingNode = newHead;
71 newHead->prev = NULL;
72 newHead->next = NULL;
73}
74
75// TODO: atomic
76cudaError_t cudaStreamCreate(cudaStream_t * pStream) {
77 // Create new stream node in linked list
78 $cuda_stream_node_t newHead = $create_new_stream_node();
79 newHead->next = $cuda_global_context.head;
80 $cuda_global_context.head->prev = newHead;
81
82 // Update cuda context's head to be the new node we created
83 $cuda_global_context.head = newHead;
84 $cuda_global_context.numStreams++;
85
86 return cudaSuccess
87}
88
89cudaError_t cudaStreamSynchronize(cudaStream_t stream) {
90 stream = $default_stream_if_null(stream);
91 $assert(stream->alive, "Attempt to synchronize with a destroyed stream");
92 $when(stream->head == NULL) return cudaSuccess;
93}
94
95$proc $destroy_stream_node($cuda_stream_node_t node) {
96 if (node->prev != NULL) {
97 node->prev->next = node->next;
98 }
99 if (node->next != NULL) {
100 node->next->prev = node->prev;
101 }
102 free(node);
103 node->stream->alive = false;
104
105 void $destroy_stream_when_complete(cudaStream_t stream) {
106 $when(stream->head==NULL) free(stream);
107 }
108 return $spawn $destroy_when_complete(node->stream);
109}
110
111// TODO: atomic
112cudaError_t cudaStreamDestroy(cudaStream_t stream) {
113 $assert(stream != NULL && stream != $cuda_default_stream, "Attempt to destroy default stream");
114 $assert(stream->alive, "Attempt to destroy an already destroyed stream);
115 $destroy_stream_node(stream->containingNode);
116 return cudaSuccess;
117}
118
119// TODO: atomic
120$cuda_op_t $stream_enqueue(_Bool deleteWhenFin, cudaStream_t stream) {
121 stream = $default_stream_if_null(stream);
122 $assert(stream->alive, "Attempt to enqueue a CUDA operation onto a destroyed stream");
123
124 $cudaop_t newOp = ($cuda_op_t) malloc(sizeof(struct $cuda_op));
125 newOp->start = false;
126 newOp->finished = false;
127 newOp->deleteWhenFin = deleteWhenFin;
128
129 $cudaop_node_t newOpNode = ($cuda_op_node_t) malloc(sizeof($cuda_op_node));
130 newOpNode->op = newOp;
131 newOpNode->next = NULL;
132
133 if (stream->tail == NULL) {
134 stream->head = newOpNode;
135 stream->tail = newOpNode;
136 newOp->start = true;
137 } else {
138 stream->tail->next = newOpNode;
139 stream->tail = newOpNode;
140 }
141 stream->numOps++;
142 return newOp;
143}
144
145// TODO: atomic
146void $stream_dequeue(cudaStream_t stream) {
147 stream = $default_stream_if_null(stream);
148 $assert(stream->head != NULL, "Attempt to dequeue an empty stream");
149
150 if (stream->head == stream->tail) {
151 stream->tail = NULL;
152 }
153
154 $cuda_op_node_t oldHead = stream->head;
155 stream->head = oldHead->next;
156 if (stream->head != NULL) {
157 stream->head->op->start = true;
158 }
159
160 $cuda_op_t finOp = oldHead->op;
161 if (finOp->deleteWhenFin) {
162 free(finOp);
163 } else {
164 finOp->finished = true;
165 }
166
167 stream->numOps--;
168}
169
170/* Need to do this in transform to get type cast right
171cudaError_t cudaMalloc(void** devPtr, size_t size) {
172 *devPtr = malloc(size) - $CUDA_HEAP_OFFSET;
173 return cudaSuccess;
174}
175*/
176
177cudaError_t cudaFree(void* devPtr) {
178 free(devPtr + $CUDA_HEAP_OFFSET);
179 return cudaSuccess;
180}
181
182void $get_true_memcpy_params(void** dst, (const void*)* src, cudaMemcpyKind* kind) {
183 cudaMemcpyKind origKind = *kind;
184 if (origKind == cudaMemcpyDeviceToDevice || origKind == cudaMemcpyDeviceToHost) {
185 *src += $CUDA_HEAP_OFFSET;
186 }
187 if (origKind == cudaMemcpyDeviceToDevice || origKind == cudaMemcpyHostToDevice) {
188 *dst += $CUDA_HEAP_OFFSET;
189 }
190 if (origKind == cudaMemcpyDefault) {
191 _Bool srcIsHost = true, dstIsHost = true;
192
193 if ($is_derefable_pointer(*src + $CUDA_HEAP_OFFSET)) {
194 *src = false;
195 trueSrc += $CUDA_HEAP_OFFSET;
196 }
197 if ($is_derefable_pointer(*dst + $CUDA_HEAP_OFFSET)) {
198 dstIsHost = false;
199 *dst += $CUDA_HEAP_OFFSET;
200 }
201
202 if(srcIsHost) {
203 *kind = dstIsHost ? cudaMemcpyHostToHost : cudaMemcpyHostToDevice;
204 } else {
205 *kind = dstIsHost ? cudaMemcpyDeviceToHost : cudaMemcpyDeviceToDevice;
206 }
207 }
208}
209
210void $cuda_memcpy_proc(void* dst, const void* src, size_t count,
211 $cuda_op_t op, cudaStream_t stream) {
212 $cuda_op_wait_start(op);
213 memcpy(dst, src, count);
214 $stream_dequeue(stream);
215}
216
217cudaError_t cudaMemcpy(void* dst, const void* src, size_t count, cudaMemcpyKind kind) {
218 void* trueSrc = src, trueDst = dst;
219 $get_true_memcpy_params(&trueSrc, &trueDst, &kind);
220
221 if (kind == cudaHostToHost) {
222 memcpy(trueDst, trueSrc, count);
223 } else {
224 _Bool waitForOp = kind != cudaMemcpyDeviceToDevice;
225 $cuda_op_t op = $stream_enqueue(!waitForOp, $cuda_default_stream);
226 $proc memcpyProc = $spawn $cuda_memcpy_proc(trueDst, trueSrc, count, op, $cuda_default_stream);
227 if (waitForOp) {
228 $wait(memcpyProc);
229 }
230 }
231
232 return cudaSuccess;
233}
234
235cudaError_t cudaMemcpyAsync(void* dst, const void* src, size_t count,
236 cudaMemcpyKind kind, cudaStream_t stream) {
237 void* trueSrc = src, trueDst = dst;
238 $get_true_memcpy_params(&trueSrc, &trueDst, &kind);
239
240 if (kind = cudaMemcpyHostToHost) {
241 memcpy(trueDst, trueSrc, count);
242 } else {
243 $cuda_op_t op = $stream_enqueue(true, stream);
244 $spawn $cuda_memcpy_proc(trueDst, trueSrc, count, op, stream);
245 }
246
247 return cudaSuccess;
248}
249
250cudaError_t cudaDeviceSynchronize() {
251 $cuda_op_t opsToWaitOn[] = ($cuda_op_t) malloc(sizeof(struct $cuda_op) *
252 $cuda_global_context.numStreams);
253 int numOps = 0;
254
255 $atomic {
256 for ($cuda_stream_node_t node = $cuda_global_context.head;
257 node != NULL;
258 node = node->next) {
259 if (node->stream->tail != NULL) {
260 opsToWaitOn[numOps] = node->stream->tail->op;
261 opsToWaitOn[numOps]->deleteWhenFin = false;
262 numOps++;
263 }
264 }
265 }
266 for (int i = 0; i < numOps; i++) {
267 $cuda_op_finish(opsToWaitOn[i]);
268 }
269
270 return cudaSuccess;
271}
272
273void $cuda_setup() {
274 $cuda_stream_node_t defaultStreamNode = $create_new_stream_node();
275 $cuda_default_stream = defaultStreamNode->stream;
276
277 $cuda_global_context.head = defaultStreamNode;
278 $cuda_global_context.count = 1;
279}
280
281void $cuda_teardown() {
282 $proc destructor = $destroy_stream_node($cuda_default_stream->containingNode);
283 $wait(destructor);
284}
285
286void _cuda_kernel_1(dim3 gridDim, dim3 blockDim, size_t _cuda_mem_size,
287 int x) {
288
289}
290void $proc_kernel_1(dim3 gridDim, dim3 blockDim, size_t _cuda_mem_size,
291 cudaStream_t _cuda_stream, $cuda_op_t _cuda_op,
292 int x) {
293 $cuda_op_wait_start(_cuda_op);
294 _cuda_kernel_1(gridDim, blockDim, _cuda_mem_size, x);
295 $stream_dequeue(_cuda_stream);
296}
297
298void _civl_main() {
299 {
300 $cuda_op_t _newOp = $stream_enqueue(true, stream);
301 $spawn $proc_kernel_1(gridDim, blockDim, 0, stream, _newOp, x);
302 }
303}
304
305int main() {
306 $cuda_setup();
307 _civl_main();
308 $cuda_teardown();
309}
Note: See TracBrowser for help on using the repository browser.