source: CIVL/examples/cuda/newCudaMockup.cvl@ 3d3af8f

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

Made changes to cuda mockup.

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

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