Advertisement
Guest User

perftest.c

a guest
Sep 7th, 2015
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.83 KB | None | 0 0
  1. //
  2. // File:       hello.c
  3. //
  4. // Abstract:   A simple "Hello World" compute example showing basic usage of OpenCL which
  5. //             calculates the mathematical square (X[i] = pow(X[i],2)) for a buffer of
  6. //             floating point values.
  7. //            
  8. //
  9. // Version:    <1.0>
  10. //
  11. // Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Inc. ("Apple")
  12. //             in consideration of your agreement to the following terms, and your use,
  13. //             installation, modification or redistribution of this Apple software
  14. //             constitutes acceptance of these terms.  If you do not agree with these
  15. //             terms, please do not use, install, modify or redistribute this Apple
  16. //             software.
  17. //
  18. //             In consideration of your agreement to abide by the following terms, and
  19. //             subject to these terms, Apple grants you a personal, non - exclusive
  20. //             license, under Apple's copyrights in this original Apple software ( the
  21. //             "Apple Software" ), to use, reproduce, modify and redistribute the Apple
  22. //             Software, with or without modifications, in source and / or binary forms;
  23. //             provided that if you redistribute the Apple Software in its entirety and
  24. //             without modifications, you must retain this notice and the following text
  25. //             and disclaimers in all such redistributions of the Apple Software. Neither
  26. //             the name, trademarks, service marks or logos of Apple Inc. may be used to
  27. //             endorse or promote products derived from the Apple Software without specific
  28. //             prior written permission from Apple.  Except as expressly stated in this
  29. //             notice, no other rights or licenses, express or implied, are granted by
  30. //             Apple herein, including but not limited to any patent rights that may be
  31. //             infringed by your derivative works or by other works in which the Apple
  32. //             Software may be incorporated.
  33. //
  34. //             The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
  35. //             WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
  36. //             WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
  37. //             PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION
  38. //             ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
  39. //
  40. //             IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
  41. //             CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  42. //             SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  43. //             INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
  44. //             AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER
  45. //             UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR
  46. //             OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  47. //
  48. // Copyright ( C ) 2008 Apple Inc. All Rights Reserved.
  49. //
  50.  
  51. ////////////////////////////////////////////////////////////////////////////////
  52.  
  53. #include <fcntl.h>
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <string.h>
  57. #include <math.h>
  58. #include <unistd.h>
  59. #include <sys/types.h>
  60. #include <sys/stat.h>
  61. #include <CL/opencl.h>
  62.  
  63. ////////////////////////////////////////////////////////////////////////////////
  64.  
  65. // Use a static data size for simplicity
  66. //
  67. #define DATA_SIZE (1048576)
  68.  
  69. ////////////////////////////////////////////////////////////////////////////////
  70.  
  71. // Simple compute kernel which computes the square of an input array
  72. //
  73. const char *KernelSource = "\n" \
  74. "__kernel void square(                                                  \n" \
  75. "   __global float* input,                                              \n" \
  76. "   __global float* output,                                             \n" \
  77. "   const unsigned int count)                                           \n" \
  78. "{                                                                      \n" \
  79. "   int i = get_global_id(0);                                           \n" \
  80. "   //if(i < count)                                                     \n" \
  81. "   output[i] = input[i] * input[i];                                    \n" \
  82. "}                                                                      \n" \
  83. "\n";
  84.  
  85. ////////////////////////////////////////////////////////////////////////////////
  86.  
  87. int main( int argc, char *argv[] )
  88. {
  89.     int err;                            // error code returned from api calls
  90.      
  91.     float *data;                        // original data set given to device
  92.     float *results;                     // results returned from device
  93.     size_t count;
  94.     unsigned int correct;               // number of correct results returned
  95.  
  96.     size_t global;                      // global domain size for our calculation
  97.     size_t local;                       // local domain size for our calculation
  98.     size_t k;
  99.     size_t i;
  100.     cl_device_id device_id;             // compute device id
  101.     cl_context context;                 // compute context
  102.     cl_command_queue commands;          // compute command queue
  103.     cl_program program;                 // compute program
  104.     cl_kernel kernel;                   // compute kernel
  105.    
  106.     cl_mem input;                       // device memory used for the input array
  107.     cl_mem output;                      // device memory used for the output array
  108.    
  109.     cl_platform_id platforms[32];           //an array to hold the IDs of all the platforms, hopefuly there won't be more than 32
  110.     cl_uint num_platforms;              //this number will hold the number of platforms on this machine
  111.     char vendor[1024];              //this strirng will hold a platforms vendor
  112.  
  113.     cl_device_id devices[32];           //this variable holds the number of devices for each platform, hopefully it won't be more than 32 per platform
  114.     cl_uint num_devices;                //this number will hold the number of devices on this machine
  115.     char deviceName[1024];              //this string will hold the devices name
  116.     cl_uint numberOfCores;              //this variable holds the number of cores of on a device
  117.     cl_long amountOfMemory;             //this variable holds the amount of memory on a device
  118.     cl_uint clockFreq;              //this variable holds the clock frequency of a device
  119.     cl_ulong maxAlocatableMem;          //this variable holds the maximum allocatable memory
  120.     cl_ulong localMem;              //this variable holds local memory for a device
  121.     cl_bool available;              //this variable holds if the device is available
  122.     int pid;                        //Platform id
  123.     // Init data arrays and count
  124.     data = malloc(sizeof(float)*DATA_SIZE);              // original data set given to device
  125.     results = malloc(sizeof(float)*DATA_SIZE);           // results returned from device
  126.     count = DATA_SIZE;
  127.     // Fill our data set with random float values
  128.     //
  129.     for(i = 0; i < DATA_SIZE; i++)
  130.         data[i] = rand() / (float)RAND_MAX;
  131.     // Connect to a compute device
  132.     //
  133.     clGetPlatformIDs(3, platforms, &num_platforms);
  134.     if (argc<2){
  135.         printf("Platform id is required. Choose from 0-2");
  136.         return 1;
  137.     }
  138.     if (sscanf (argv[1], "%i", &pid)!=1) {
  139.         printf ("error - not an integer");
  140.         return 1;
  141.     }
  142.     err = clGetDeviceIDs(platforms[pid], CL_DEVICE_TYPE_ALL, 1, &device_id, NULL);
  143.     if (err != CL_SUCCESS)
  144.     {
  145.         printf("Error: Failed to create a device group!\n");
  146.         return EXIT_FAILURE;
  147.     } else {
  148.         printf("Succeeded to create a device group!\n");
  149.     }
  150.  
  151.     //scan in device information
  152.     clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(deviceName), deviceName, NULL);
  153.     clGetDeviceInfo(device_id, CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL);
  154.     clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(numberOfCores), &numberOfCores, NULL);
  155.     clGetDeviceInfo(device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(amountOfMemory), &amountOfMemory, NULL);
  156.     clGetDeviceInfo(device_id, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(clockFreq), &clockFreq, NULL);
  157.     clGetDeviceInfo(device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(maxAlocatableMem), &maxAlocatableMem, NULL);
  158.     clGetDeviceInfo(device_id, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(localMem), &localMem, NULL);
  159.     clGetDeviceInfo(device_id, CL_DEVICE_AVAILABLE, sizeof(available), &available, NULL);
  160.  
  161.  
  162.     //print out device information
  163.     printf("\tDevice: %u\n", pid);
  164.     printf("\t\tName:\t\t\t\t%s\n", deviceName);
  165.     printf("\t\tVendor:\t\t\t\t%s\n", vendor);
  166.     printf("\t\tAvailable:\t\t\t%s\n", available ? "Yes" : "No");
  167.     printf("\t\tCompute Units:\t\t\t%u\n", numberOfCores);
  168.     printf("\t\tClock Frequency:\t\t%u mHz\n", clockFreq);
  169.     printf("\t\tGlobal Memory:\t\t\t%0.00f mb\n", (double)amountOfMemory/1048576);
  170.     printf("\t\tMax Allocateable Memory:\t%0.00f mb\n", (double)maxAlocatableMem/1048576);
  171.     printf("\t\tLocal Memory:\t\t\t%u kb\n\n", (unsigned int)localMem);
  172.     // Create a compute context
  173.     //
  174.     context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
  175.     if (!context)
  176.     {
  177.         printf("Error: Failed to create a compute context!\n");
  178.         return EXIT_FAILURE;
  179.     } else {
  180.         printf("Succeeded to create a compute context!\n");
  181.     }
  182.  
  183.     // Create a command commands
  184.     //
  185.     commands = clCreateCommandQueue(context, device_id, 0, &err);
  186.     if (!commands)
  187.     {
  188.         printf("Error: Failed to create a command commands!\n");
  189.         return EXIT_FAILURE;
  190.     } else {
  191.         printf("Succeeded to create a command commands!\n");
  192.     }
  193.  
  194.     // Create the compute program from the source buffer
  195.     //
  196.     program = clCreateProgramWithSource(context, 1, (const char **) & KernelSource, NULL, &err);
  197.     if (!program)
  198.     {
  199.         printf("Error: Failed to create compute program!\n");
  200.         return EXIT_FAILURE;
  201.     } else {
  202.         printf("Succeeded to create compute program!\n");
  203.     }
  204.  
  205.     // Build the program executable
  206.     //
  207.     err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
  208.     if (err != CL_SUCCESS)
  209.     {
  210.         size_t len;
  211.         char buffer[2048];
  212.  
  213.         printf("Error: Failed to build program executable!\n");
  214.         clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
  215.         printf("%s\n", buffer);
  216.         exit(1);
  217.     } else {
  218.         printf("Succeeded to create program executable!\n");
  219.     }
  220.  
  221.     // Create the compute kernel in the program we wish to run
  222.     //
  223.     kernel = clCreateKernel(program, "square", &err);
  224.     if (!kernel || err != CL_SUCCESS)
  225.     {
  226.         printf("Error: Failed to create compute kernel!\n");
  227.         exit(1);
  228.     } else {
  229.         printf("Succeeded to create compute kernel!\n");
  230.     }
  231.     for(k = 0; k<9999; k++){
  232.         // Create the input and output arrays in device memory for our calculation
  233.         //
  234.         input = clCreateBuffer(context,  CL_MEM_READ_ONLY,  sizeof(float) * DATA_SIZE, NULL, NULL);
  235.         output = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(float) * DATA_SIZE, NULL, NULL);
  236.         if (!input || !output)
  237.         {
  238.             printf("Error: Failed to allocate device memory!\n");
  239.             exit(1);
  240.         }    
  241.        
  242.         // Write our data set into the input array in device memory
  243.         //
  244.         err = clEnqueueWriteBuffer(commands, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, data, 0, NULL, NULL);
  245.         if (err != CL_SUCCESS)
  246.         {
  247.             printf("Error: Failed to write to source array!\n");
  248.             exit(1);
  249.         }
  250.  
  251.         // Set the arguments to our compute kernel
  252.         //
  253.         err = 0;
  254.         err  = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input);
  255.         err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &output);
  256.         err |= clSetKernelArg(kernel, 2, sizeof(unsigned int), &count);
  257.         if (err != CL_SUCCESS)
  258.         {
  259.             printf("Error: Failed to set kernel arguments! %d\n", err);
  260.             exit(1);
  261.         }
  262.  
  263.         // Get the maximum work group size for executing the kernel on the device
  264.         //
  265.         err = clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_WORK_GROUP_SIZE, sizeof(local), &local, NULL);
  266.         if (err != CL_SUCCESS)
  267.         {
  268.             printf("Error: Failed to retrieve kernel work group info! %d\n", err);
  269.             exit(1);
  270.         }
  271.  
  272.         // Execute the kernel over the entire range of our 1d input data set
  273.         // using the maximum number of work group items for this device
  274.         //
  275.         global = count;
  276.         err = clEnqueueNDRangeKernel(commands, kernel, 1, NULL, &count, NULL, 0, NULL, NULL);
  277.         if (err)
  278.         {
  279.             printf("Error: Failed to execute kernel!\n");
  280.             return EXIT_FAILURE;
  281.         }
  282.  
  283.         // Wait for the command commands to get serviced before reading back results
  284.         //
  285.         clFinish(commands);
  286.  
  287.         // Read back the results from the device to verify the output
  288.         //
  289.         err = clEnqueueReadBuffer( commands, output, CL_TRUE, 0, sizeof(float) * DATA_SIZE, results, 0, NULL, NULL );  
  290.         if (err != CL_SUCCESS)
  291.         {
  292.             printf("Error: Failed to read output array! %d\n", err);
  293.             exit(1);
  294.         }
  295.        
  296.         // Validate our results
  297.         //
  298.         correct = 0;
  299.         for(i = 0; i < DATA_SIZE; i++)
  300.         {
  301.             if(results[i] == data[i] * data[i])
  302.                 correct++;
  303.         }
  304.        
  305.         // Print a brief summary detailing the results
  306.         //
  307.         //printf("Computed '%d/%d' correct values!\n", correct, count);
  308.        
  309.         // Shutdown and cleanup
  310.         //
  311.         clReleaseMemObject(input);
  312.         clReleaseMemObject(output);
  313.     }
  314.     clReleaseProgram(program);
  315.     clReleaseKernel(kernel);
  316.     clReleaseCommandQueue(commands);
  317.     clReleaseContext(context);
  318.  
  319.     return 0;
  320. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement