Advertisement
Guest User

opencl host program with chunks

a guest
Sep 1st, 2014
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.47 KB | None | 0 0
  1. /* Create program from a file and compile it */
  2. cl_program build_program(cl_context ctx, cl_device_id dev, const char *filename, const char *options) {
  3.     cl_program program;
  4.     FILE *program_handle;
  5.     char *program_buffer, *program_log;
  6.     size_t program_size, log_size;
  7.     int err;
  8.  
  9.     /* Read program file and place content into buffer */
  10.     program_handle = fopen(filename, "r");
  11.     if (program_handle == NULL) {
  12.         perror("Couldn't find the program file");
  13.         client_cleanup(EXIT_FAILURE);
  14.     }
  15.  
  16.     fseek(program_handle, 0, SEEK_END);
  17.     program_size = ftell(program_handle);
  18.     rewind(program_handle);
  19.     program_buffer = (char *) malloc(program_size + 1);
  20.     program_buffer[program_size] = '\0';
  21.     fread(program_buffer, sizeof(char), program_size, program_handle);
  22.     fclose(program_handle);
  23.  
  24.     /* Create program from file */
  25.     program = clCreateProgramWithSource(ctx, 1,
  26.                         (const char **) &program_buffer, &program_size, &err);
  27.     if (err < 0) {
  28.         perror("Couldn't create the program");
  29.         client_cleanup(EXIT_FAILURE);
  30.     }
  31.  
  32.     free(program_buffer);
  33.  
  34.     /* Build program */
  35.     err = clBuildProgram(program, 0, NULL, options, NULL, NULL);
  36.  
  37.     if (err < 0) {
  38.         /* Find size of log and print to std output */
  39.         clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG,
  40.                       0, NULL, &log_size);
  41.  
  42.         program_log = (char *) malloc(log_size + 1);
  43.         program_log[log_size] = '\0';
  44.         clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG,
  45.                       log_size + 1, program_log, NULL);
  46.  
  47.         printf("%s\n", program_log);
  48.         free(program_log);
  49.         client_cleanup(EXIT_FAILURE);
  50.     }
  51.  
  52.     return(program);
  53. }
  54.  
  55. int str2ull(char *str, uint64_t *val)
  56. {
  57.     char *end;
  58.     uint64_t ret;
  59.  
  60.     if (!str)
  61.         return(-1);
  62.  
  63.     int i = 0;
  64.     while (isspace(str[i]))
  65.         i++;
  66.  
  67.     if (str[i] == '-') { // BUG: -0001
  68.         i++;
  69.  
  70.         if (!str[i] || str[i] != '0')
  71.             return(-4);
  72.     }
  73.  
  74.     errno = 0;
  75.     ret = strtoull(str, &end, 10);
  76.  
  77.     if (*end)
  78.         return(-2);
  79.  
  80.     if (ret == ULLONG_MAX && errno == ERANGE)
  81.         return(-3);
  82.  
  83.     *val = ret;
  84.     return(0);
  85. }
  86.  
  87. size_t get_chunks(uint64_t begin, uint64_t end, size_t size)
  88. {
  89.     size_t n;
  90.  
  91.     n = (end - begin +1) / size;
  92.     if ((end - begin +1) % size > 0)
  93.         n++;
  94.  
  95.     return(n);
  96. }
  97.  
  98. int fill_array(cl_ulong2 *dst, chunk_t chunk, unsigned int packets)
  99. {
  100.     unsigned int i;
  101.     uint64_t packet_size;
  102.     uint64_t last_packet;
  103.  
  104. /*
  105.     test input number range to be divisible by the packet count
  106. */
  107.  
  108.     if ((chunk.last - chunk.first +1) % packets == 0) {
  109.         packet_size = (chunk.last - chunk.first +1) / packets;
  110.         last_packet = packet_size;
  111.     }
  112.     else {
  113.         packet_size = (chunk.last - chunk.first +1) / (packets -1);
  114.         last_packet = (chunk.last - chunk.first +1) % (packets -1);
  115.     }
  116.  
  117.     debug("packet_size: %llu\n", packet_size);
  118.     debug("last_packet: %llu\n", last_packet);
  119.  
  120. /*
  121.     input range too small
  122.     fill up the buffer with dummy data
  123. */
  124.  
  125.     if (packet_size == 0) {
  126.         debug("packet_size = 0\n");
  127.         debug("filling up %u packets with dummy data\n", packets -1);
  128.         for (i = 0; i < packets -1; i++) {
  129.             dst[i].s0 = 42;
  130.             dst[i].s1 = 42;
  131.         }
  132.     }
  133.     else {
  134.         /* Initialize data */
  135.         for (i = 0; i < packets -1; i++) {
  136.             dst[i].s0 = chunk.first + i * packet_size;
  137.             dst[i].s1 = chunk.first + i * packet_size + packet_size -1;
  138.         }
  139.     }
  140.  
  141. /*
  142.     assign last element in array
  143. */
  144.     if (last_packet == 0) {
  145.         debug("last_packet = 0\n");
  146.         dst[i].s0 = 42;
  147.         dst[i].s1 = 42;
  148.     }
  149.     else {
  150.         dst[i].s0 = chunk.first + i * packet_size;
  151.         dst[i].s1 = chunk.last;
  152.     }
  153.  
  154.     debug("last_packet_begin: %llu\n", dst[i].s0);
  155.     debug("last_packet_end: %llu\n", dst[i].s1);
  156.  
  157.     return(0);
  158. }
  159.  
  160. void sleeptime(time_t sec, long int nsec)
  161. {
  162.     struct timespec t;
  163.     t.tv_sec = sec;
  164.     t.tv_nsec = nsec;
  165.  
  166.     while (nanosleep(&t, &t) == -1 && errno == EINTR)
  167.         ;
  168. }
  169.  
  170. int main(int argc, char *argv[])
  171. {
  172.     /* OpenCL structures */
  173.     cl_device_id device;
  174.     cl_context context;
  175.     cl_program program;
  176.     cl_kernel kernel;
  177.     cl_command_queue queue;
  178.     cl_int err;
  179.     size_t local_size, global_size;
  180.     unsigned int i;
  181.  
  182.     uint64_t begin;
  183.     if (str2ull(strtok(argv[2], ";"), &begin) < 0) {
  184.         printerr("begin invalid");
  185.         client_cleanup(EXIT_FAILURE);
  186.     }
  187.  
  188.     uint64_t end;
  189.     if (str2ull(strtok(NULL, ";"), &end) < 0) {
  190.         printerr("end invalid");
  191.         client_cleanup(EXIT_FAILURE);
  192.     }
  193.  
  194.     if (begin > end) {
  195.         printerr("begin > end");
  196.         client_cleanup(EXIT_FAILURE);
  197.     }
  198.  
  199.     debug("begin: %llu\n", begin);
  200.     debug("end: %llu\n", end);
  201.  
  202.     /* Data and buffers */
  203.     cl_ulong2 input_data[PACKET_COUNT];
  204.     cl_int output_data[PACKET_COUNT];
  205.  
  206.     cl_mem input_buffer, output_buffer;
  207.  
  208.     /* Get a Device */
  209.     if (ocldevid(argv[1], &device)) {
  210.         printerr("ocldevid() failed");
  211.         client_cleanup(EXIT_FAILURE);
  212.     }
  213.  
  214.     /* Create a context */
  215.     context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
  216.  
  217.     if (err < 0) {
  218.         perror("Couldn't create a context");
  219.         client_cleanup(EXIT_FAILURE);
  220.     }
  221.  
  222.     /* Build program */
  223.     program = build_program(context, device, PROGRAM_FILE, "");
  224.  
  225.     /* Create a kernel */
  226.     kernel = clCreateKernel(program, KERNEL_FUNC, &err);
  227.  
  228.     if (err < 0) {
  229.         perror("Couldn't create a kernel");
  230.         client_cleanup(EXIT_FAILURE);
  231.     }
  232.  
  233.     /* Create a command queue */
  234.     queue = clCreateCommandQueue(context, device, 0, &err);
  235.  
  236.     if (err < 0) {
  237.         perror("Couldn't create a command queue");
  238.         client_cleanup(EXIT_FAILURE);
  239.     }
  240.  
  241.     input_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY,
  242.                 PACKET_COUNT * sizeof(cl_ulong2), NULL, &err);
  243.  
  244.     output_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
  245.                 PACKET_COUNT * sizeof(cl_int), NULL, &err);
  246.  
  247.     if (err < 0) {
  248.         perror("Couldn't create a buffer");
  249.         client_cleanup(EXIT_FAILURE);
  250.     }
  251.  
  252.     local_size = GROUP_SIZE;
  253.     global_size = PACKET_COUNT;
  254.  
  255.     debug("local_size: %zu\n", local_size);
  256.     debug("global_size: %zu\n", global_size);
  257.  
  258.     chunk_t current_chunk = { .id = 0, };
  259.     size_t chunk_count;
  260.  
  261.     chunk_count = get_chunks(begin, end, CHUNK_SIZE);
  262.  
  263.     debug("chunk_count: %zu\n", chunk_count);
  264.  
  265.     debug("NUM_PER_THREAD: %lu\n", NUM_PER_THREAD);
  266.     debug("CHUNK_SIZE: %zu\n", CHUNK_SIZE);
  267.  
  268.     while (current_chunk.id != chunk_count) {
  269.         /* Initialise output array */
  270.         memset(output_data, -1, sizeof(output_data));
  271.  
  272.         debug("current_chunk: %zu\n", current_chunk.id);
  273.         current_chunk.first = begin + current_chunk.id * CHUNK_SIZE;
  274.         debug("current_chunk.first: %zu\n", current_chunk.first);
  275.  
  276.         /* Check for last chunk */
  277.         if (current_chunk.id == chunk_count -1)
  278.             current_chunk.last = current_chunk.first + (end - begin) % CHUNK_SIZE;
  279.         else
  280.             current_chunk.last = current_chunk.first + CHUNK_SIZE -1;
  281.  
  282.         debug("current_chunk.last: %zu\n", current_chunk.last);
  283.  
  284.         /* Fill input array with data*/
  285.         if (fill_array(input_data, current_chunk, PACKET_COUNT) < 0) {
  286.             printerr("fill_array() failed");
  287.             client_cleanup(EXIT_FAILURE);
  288.         }
  289.  
  290.         /* Copy input data to device */
  291.         err = clEnqueueWriteBuffer(queue, input_buffer, CL_TRUE, 0,
  292.                     sizeof(input_data), input_data, 0, NULL, NULL);
  293.  
  294.         if (err < 0) {
  295.             perror("Couldn't write the buffer");
  296.             client_cleanup(EXIT_FAILURE);
  297.         }
  298.  
  299.         /* Create kernel arguments */
  300.         err = clSetKernelArg(kernel, 0, sizeof(input_buffer), &input_buffer);
  301.         err |= clSetKernelArg(kernel, 1, sizeof(output_buffer), &output_buffer);
  302.  
  303.         if (err < 0) {
  304.             perror("Couldn't create a kernel argument");
  305.             client_cleanup(EXIT_FAILURE);
  306.         }
  307.  
  308.         debug("enqueueing kernel\n");
  309.  
  310.         /* Enqueue kernel */
  311.         err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_size,
  312.                     &local_size, 0, NULL, NULL);
  313.  
  314.         if (err < 0) {
  315.             perror("Couldn't enqueue the kernel");
  316.             client_cleanup(EXIT_FAILURE);
  317.         }
  318.  
  319.         /* Read the kernel's output */
  320.         err = clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0,
  321.                     sizeof(output_data), output_data, 0, NULL, NULL);
  322.  
  323.         if (err < 0) {
  324.             perror("Couldn't read the buffer");
  325.             client_cleanup(EXIT_FAILURE);
  326.         }
  327.  
  328.         /* Print packets */
  329.         for (i = 0; i < PACKET_COUNT; i++) {
  330.             switch (output_data[i]) {
  331.                 case -1:
  332.                     /* search failed */
  333.                     debug("[%llu,%llu]: failure\n", input_data[i].s0, input_data[i].s1);
  334.                     break;
  335.                 case 0:
  336.                     /* no solution found */
  337.                     break;
  338.                 case 1:
  339.                     /* solution found */
  340.                     debug("[%llu,%llu]: success\n", input_data[i].s0, input_data[i].s1);
  341.                     break;
  342.             }
  343.         }
  344.  
  345.         sleeptime(WAIT_SEC, WAIT_NSEC);
  346.  
  347.         current_chunk.id++;
  348.     }
  349.  
  350.     /* Deallocate resources */
  351.     clReleaseMemObject(output_buffer);
  352.     clReleaseMemObject(input_buffer);
  353.     clReleaseCommandQueue(queue);
  354.     clReleaseKernel(kernel);
  355.     clReleaseProgram(program);
  356.     clReleaseContext(context);
  357.  
  358.     client_cleanup(EXIT_SUCCESS);
  359. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement