File: multqueues.c

package info (click to toggle)
oclgrind 21.10-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 3,216 kB
  • sloc: cpp: 21,369; ansic: 6,395; lisp: 1,122; python: 124; makefile: 19
file content (202 lines) | stat: -rw-r--r-- 5,891 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "common.h"

#include <stdio.h>
#include <stdlib.h>

#define MQ_BUFSIZE 128

typedef enum
{
  MQ_WAIT_FOR_EVENTS,
  MQ_FINISH
} WaitType;

void write_read_test(cl_context ctx, cl_device_id dev, cl_command_queue cq1,
                     cl_command_queue cq2, WaitType wait_type, char* test_name)
{
  // Variables
  cl_int err;
  cl_float* buf_host1A = (cl_float*)malloc(MQ_BUFSIZE * sizeof(cl_float));
  cl_float* buf_host1B = (cl_float*)calloc(MQ_BUFSIZE, sizeof(cl_float));
  cl_mem buf_dev1 = NULL;
  cl_int* buf_host2A = (cl_int*)malloc(MQ_BUFSIZE * sizeof(cl_int));
  cl_int* buf_host2B = (cl_int*)calloc(MQ_BUFSIZE, sizeof(cl_int));
  cl_mem buf_dev2 = NULL;
  cl_event ew[2] = {NULL, NULL}, er[2] = {NULL, NULL};
  cl_uint i;

  // Fill host buffers with random data
  for (i = 0; i < MQ_BUFSIZE; i++)
  {
    buf_host1A[i] = rand() / (cl_float)RAND_MAX;
    buf_host2A[i] = (cl_int)rand();
  }

  // Create device buffers
  buf_dev1 = clCreateBuffer(ctx, CL_MEM_READ_WRITE,
                            MQ_BUFSIZE * sizeof(cl_float), NULL, &err);
  checkError(err, "creating device buffer 1");
  buf_dev2 = clCreateBuffer(ctx, CL_MEM_READ_WRITE, MQ_BUFSIZE * sizeof(cl_int),
                            NULL, &err);
  checkError(err, "creating device buffer 2");

  // Write something to device buffer 1 using command queue 1,
  // generate event ew[0]
  err = clEnqueueWriteBuffer(cq1, buf_dev1, CL_FALSE, 0,
                             MQ_BUFSIZE * sizeof(cl_float), buf_host1A, 0, NULL,
                             &ew[0]);
  checkError(err, "writing to buffer 1");

  // Write something to device buffer 2 using command queue 2,
  // generate event ew[1]
  err = clEnqueueWriteBuffer(cq2, buf_dev2, CL_FALSE, 0,
                             MQ_BUFSIZE * sizeof(cl_int), buf_host2A, 0, NULL,
                             &ew[1]);
  checkError(err, "writing to buffer 2");

  // Read from device buffer 1 using command queue 2, make it depend
  // on event ew[0] and generate event er[0]
  err = clEnqueueReadBuffer(cq2, buf_dev1, CL_FALSE, 0,
                            MQ_BUFSIZE * sizeof(cl_float), buf_host1B, 1,
                            &ew[0], &er[0]);
  checkError(err, "reading from buffer 1");

  // Read from device buffer 2 using command queue 1, make it depend
  // on event ew[1] and generate event er[1]
  err =
    clEnqueueReadBuffer(cq1, buf_dev2, CL_FALSE, 0, MQ_BUFSIZE * sizeof(cl_int),
                        buf_host2B, 1, &ew[1], &er[1]);
  checkError(err, "reading from buffer 1");

  // Wait on host thread for work to finish
  switch (wait_type)
  {
  case MQ_WAIT_FOR_EVENTS:
    // Wait on host thread for read events
    clWaitForEvents(2, er);
    break;
  case MQ_FINISH:
    // Wait on host thread for queues to be processed
    clFinish(cq1);
    // If they're not the same queue, must also wait in the second queue
    if (cq1 != cq2)
    {
      clFinish(cq2);
    }
    break;
  default:
    fprintf(stderr, "Unknown wait type\n");
    exit(1);
  }

  // Check results
  for (i = 0; i < MQ_BUFSIZE; i++)
  {
    if (buf_host1A[i] != buf_host1B[i] || buf_host2A[i] != buf_host2B[i])
    {
      fprintf(stderr, "Incorrect results in test %s\n", test_name);
      exit(1);
    }
  }

  // If we get here everything is OK
  printf("OK\n");

  // Release stuff
  for (i = 0; i < 2; i++)
  {
    clReleaseEvent(ew[i]);
    clReleaseEvent(er[i]);
  }
  clReleaseMemObject(buf_dev1);
  clReleaseMemObject(buf_dev2);
  free(buf_host1A);
  free(buf_host1B);
  free(buf_host2A);
  free(buf_host2B);
}

int main(int argc, char* argv[])
{
  ///////////
  // Setup //
  ///////////

  // Variables
  cl_platform_id platf;
  cl_context ctx = NULL;
  cl_device_id dev;
  cl_int err;
  cl_command_queue cq1 = NULL, cq2 = NULL, oocq = NULL;

  // Initialize PRNG
  srand(0);

  // Get platform
  err = clGetPlatformIDs(1, &platf, NULL);
  checkError(err, "getting platform");

  // Check its Oclgrind
  checkOclgrindPlatform(platf);

  // Get first device
  err = clGetDeviceIDs(platf, CL_DEVICE_TYPE_ALL, 1, &dev, NULL);
  checkError(err, "getting device");

  // Create context
  ctx = clCreateContext(NULL, 1, &dev, NULL, NULL, &err);
  checkError(err, "creating context");

  ////////////////////////////////
  // Test 1: Two command queues //
  ////////////////////////////////

  // Create first command queue
  cq1 = clCreateCommandQueue(ctx, dev, 0, &err);
  checkError(err, "creating first command queue");

  // Create second command queue
  cq2 = clCreateCommandQueue(ctx, dev, 0, &err);
  checkError(err, "creating second command queue");

  // Test 1.1: Perform test with two different command queues and explicitly
  // waiting for events
  write_read_test(ctx, dev, cq1, cq2, MQ_WAIT_FOR_EVENTS, "test 1.1");

  // Test 1.2: Perform test with two different command queues and wait for
  // the second queue to finish
  write_read_test(ctx, dev, cq1, cq2, MQ_FINISH, "test 1.2");

  // Release command queues
  clReleaseCommandQueue(cq2);
  clReleaseCommandQueue(cq1);

  ////////////////////////////////////////////
  // Test 2: One out-of-order command queue //
  ////////////////////////////////////////////

  // Create an out-of-order command queue
  oocq = clCreateCommandQueue(ctx, dev, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
                              &err);
  checkError(err, "creating out-of-order command queue");

  // Test 2.1: Perform test with out-of-order command queue and explicitly
  // waiting for events
  write_read_test(ctx, dev, oocq, oocq, MQ_WAIT_FOR_EVENTS, "test 2.1");

  // Test 2.2: Perform test with out-of-order command queue and wait for
  // queue to finish
  write_read_test(ctx, dev, oocq, oocq, MQ_FINISH, "test 2.2");

  // Release command queue
  clReleaseCommandQueue(oocq);

  //////////////
  // Clean-up //
  //////////////

  // Release context
  clReleaseContext(ctx);

  return 0;
}