OpenCL矩阵转置

介绍

矩阵转置,主要的技巧还是利用好local memory ,防止local memory,以及glabol memory的读取尽量是合并读写。

完整代码一:

main.cpp代码

  1. #include <iostream>  
  2. #include <string>  
  3. #include <fstream>  
  4. #include <sstream>  
  5. #include <time.h>  
  6.   
  7. #ifdef _APPLE_  
  8. #include <OpenCL/OpenCL.h>  
  9. #else  
  10. #include <CL/cl.h>  
  11. #endif  
  12.   
  13. #define MATRIXMULLTIPLY  
  14.   
  15. #define N  6  
  16. #define K  8  
  17. #define L  5  
  18.   
  19. //Functio to check and handle OpenCL errors  
  20. inline void checkErr(cl_int err,const char *name)  
  21. {  
  22.     if(err !=CL_SUCCESS)  
  23.     {  
  24.         std::cerr <<"ERROR: "<< name <<"("<<err<< ")"<<std::endl;  
  25.         exit(EXIT_FAILURE);  
  26.     }  
  27. }  
  28. cl_context CreateContext()  
  29. {  
  30.     cl_int errNum;  
  31.     cl_uint numPlatforms;  
  32.     cl_platform_id firstPlatformId;  
  33.     cl_context context = NULL;  
  34.   
  35.     // First, select an OpenCL platform to run on.  For this example, we simply choose the first available platform.  Normally, you would  
  36.     // query for all available platforms and select the most appropriate one.  
  37.     errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlatforms);  
  38.     if (errNum != CL_SUCCESS || numPlatforms <= 0)  
  39.     {  
  40.         std::cerr << "Failed to find any OpenCL platforms." << std::endl;  
  41.         return NULL;  
  42.     }  
  43.   
  44.     // Next, create an OpenCL context on the platform.  Attempt to create a GPU-based context, and if that fails, try to create  
  45.     // a CPU-based context.  
  46.     cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM,(cl_context_properties)firstPlatformId, 0 };  
  47.   
  48.     context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU,NULL, NULL, &errNum);  
  49.     if (errNum != CL_SUCCESS)  
  50.     {  
  51.         std::cout << "Could not create GPU context, trying CPU..." << std::endl;  
  52.         context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_CPU,NULL, NULL, &errNum);  
  53.         if (errNum != CL_SUCCESS)  
  54.         {  
  55.             std::cerr << "Failed to create an OpenCL GPU or CPU context." << std::endl;  
  56.             return NULL;  
  57.         }  
  58.     }  
  59.   
  60.     return context;  
  61. }  
  62.   
  63. int main( int argc, char * argv[])  
  64. {  
  65.     // Use the first platform  
  66.     cl_int errNum;  
  67.     cl_platform_id platformID;  
  68.     cl_context context =NULL;  
  69.     cl_device_id  device;  
  70.     
  71.     errNum = clGetPlatformIDs(1,&platformID,NULL);  
  72.     checkErr(errNum,"clGetPlatformIDS");  
  73.     std::cout<<"Platform ID: "<<platformID<<std::endl;  
  74.   
  75.     context = CreateContext( );  
  76.     if(context == NULL)  
  77.     {  
  78.         std::cerr << "Failed to create OpenCL context." << std::endl;  
  79.         return NULL;  
  80.     }  
  81.   
  82.     errNum = clGetDeviceIDs(platformID,CL_DEVICE_TYPE_GPU,1,&device,NULL);  
  83.   
  84.     if(errNum !=CL_SUCCESS)  
  85.     {  
  86.         std::cerr <<"Could not create CL_DEVICE_TYPE_GPU context, trying CL_DEVICE_TYPE_CPU..."<<std::endl;  
  87.         errNum =clGetDeviceIDs(platformID,CL_DEVICE_TYPE_CPU,1,&device,NULL);  
  88.         std::cout <<"Device: "<<device<<std::endl;  
  89.         if(errNum !=CL_SUCCESS)  
  90.         {  
  91.             checkErr(errNum,"clGetDeviceIDs(..CL_DEVICE_TYPE_ALL..)");  
  92.         }  
  93.     }  
  94.   
  95.     cl_command_queue commandQueue = clCreateCommandQueue(context,device,0,&errNum);  
  96.     checkErr(errNum,"clCreateCommandQueue( )");  
  97.   
  98.     cl_int Mat_A_width  = N;  
  99.     cl_int Mat_A_height = K;  
  100.     cl_int Mat_B_width  = K;  
  101.     cl_int Mat_B_height = L;  
  102.   
  103.     float *MatA =(float*)malloc(sizeof(float)*Mat_A_width*Mat_A_height);  
  104.   
  105.     if(MatA ==NULL)  
  106.     {  
  107.         std::cerr<<"Failed to  Allocationing Memmey ."<<std::endl;  
  108.     }  
  109.   
  110. #ifdef MATRIXMULLTIPLY  
  111.     float *MatB =(float*)malloc(sizeof(float)*Mat_B_width*Mat_B_height);  
  112.     float *MatC =(float*)malloc(sizeof(float)*Mat_A_width*Mat_B_height);  
  113. #else  
  114.     float *MatC =(float*)malloc(sizeof(float)*Mat_A_width*Mat_A_height);  
  115. #endif  
  116.   
  117.     std::cout<<"=====MatA: " << Mat_A_width << "X" << Mat_A_height ;//<< std::endl;  
  118.     for(int i = 0; i< Mat_A_width*Mat_A_height; i++)  
  119.     {  
  120.         MatA[i] = std::rand()*0.25;  
  121.         //MatA[i] = 4.5;  
  122.       
  123.         if((i%Mat_A_height ==0)||(i == 0))  
  124.         {  
  125.             std::cout << std::endl;  
  126.         }  
  127.         std::cout<<MatA[i]<< "\t";  
  128.     }  
  129.     std::cout<<std::endl;  
  130.   
  131.     //Allocate space for Matrix A on the device  
  132.     cl_mem bufferA = clCreateBuffer(context,  
  133.                                     CL_MEM_READ_ONLY,//|CL_MEM_COPY_HOST_PTR,  
  134.                                     Mat_A_width*Mat_A_height*sizeof(float),  
  135.                                     NULL,  
  136.                                     &errNum);  
  137.     checkErr(errNum,"clCreateBuffer(...bufferA..)");  
  138.     errNum = clEnqueueWriteBuffer(commandQueue,bufferA,CL_TRUE,0,Mat_A_width*Mat_A_height*sizeof(float),(void*)MatA, 0, NULL,NULL);  
  139.   
  140. #ifdef MATRIXMULLTIPLY  
  141.     std::cout<<"MatB: "<<Mat_B_width <<"X"<<Mat_B_height<<std::endl;  
  142.     for(int i = 0; i< Mat_B_width*Mat_B_height; i++)  
  143.     {  
  144.         MatB[i] = std::rand()*0.25;  
  145.         //MatB[i] = 2.0;  
  146.         if((i%Mat_B_height ==0)||(i == 0))  
  147.         {  
  148.             std::cout << std::endl;  
  149.         }  
  150.         std::cout<<MatA[i]<< " ";  
  151.     }  
  152.     std::cout<<std::endl;  
  153.     //Allocate space for Matrix B on the device  
  154.     cl_mem bufferB = clCreateBuffer(context,  
  155.                                     CL_MEM_READ_ONLY,//|CL_MEM_COPY_HOST_PTR,  
  156.                                     Mat_B_width*Mat_B_height*sizeof(float),  
  157.                                     NULL,  
  158.                                     &errNum);  
  159.     checkErr(errNum,"clCreateBuffer(...bufferB..)");  
  160.   
  161.     //Copy Matrix B to the device  
  162.     errNum = clEnqueueWriteBuffer(commandQueue,bufferB,CL_TRUE, 0,Mat_B_width*Mat_B_height*sizeof(float),(void*)MatB,0,NULL,NULL);  
  163.   
  164.   
  165.     //Allocate space for Matrix C on the device  
  166.     cl_mem bufferC = clCreateBuffer(context,  
  167.                                     CL_MEM_READ_ONLY,//|CL_MEM_COPY_HOST_PTR,  
  168.                                     Mat_A_width*Mat_B_height*sizeof(float),  
  169.                                     NULL,  
  170.                                     &errNum);  
  171.     checkErr(errNum,"clCreateBuffer(...bufferC..)");  
  172. #else  
  173.     //Allocate space for Matrix C on the device  
  174.     cl_mem bufferC = clCreateBuffer(context,  
  175.                                     CL_MEM_READ_ONLY,//|CL_MEM_COPY_HOST_PTR,  
  176.                                     Mat_A_width*Mat_A_height*sizeof(float),  
  177.                                     NULL,  
  178.                                     &errNum);  
  179.     checkErr(errNum,"clCreateBuffer(...bufferC..)");  
  180. #endif    
  181.   
  182.     // We assume that the program source si stroed int the variable  
  183.     cl_program program;  
  184.     const char* fileName = "Matrixkernel.cl";  
  185.     std::ifstream kernelFile(fileName,std::ios::in);  
  186.   
  187.     if( !kernelFile.is_open())  
  188.     {  
  189.         std::cerr <<"Failed to open file reading:"<<fileName<<std::endl;  
  190.         return NULL;  
  191.     }  
  192.   
  193.     std::ostringstream oss;  
  194.     oss << kernelFile.rdbuf();  
  195.   
  196.     std::string srcStdStr = oss.str();  
  197.     const char *srcStr = srcStdStr.c_str();  
  198.     program = clCreateProgramWithSource(context, 1,(const char**)&srcStr,NULL, NULL);  
  199.     if (program == NULL)  
  200.     {  
  201.         std::cerr << "Failed to create OpenCL program from source." << std::endl;  
  202.         return NULL;  
  203.     }  
  204.   
  205.     errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);  
  206.     if (errNum != CL_SUCCESS)  
  207.     {  
  208.         // Determine the reason for the error  
  209.         char buildLog[16384];  
  210.         clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,sizeof(buildLog), buildLog, NULL);  
  211.   
  212.         std::cerr << "Error in kernel: " << std::endl;  
  213.         std::cerr << buildLog;  
  214.         clReleaseProgram(program);  
  215.         return NULL;  
  216.     }  
  217. #ifdef  MATRIXMULLTIPLY  
  218.     // Create the kernel  
  219.     cl_kernel kernel = clCreateKernel(program,"MulltiplySample",NULL);  
  220.     if(kernel ==NULL)  
  221.     {  
  222.         std::cerr<<"Faile to create kernel."<<std::endl;  
  223.         return NULL;  
  224.     }  
  225.   
  226.     //set the kernel arguments  
  227.     clSetKernelArg(kernel, 0,sizeof(cl_mem), (void*) &bufferC);  
  228.     clSetKernelArg(kernel, 1,sizeof(cl_int), (void*) &Mat_A_width);  
  229.     clSetKernelArg(kernel, 2,sizeof(cl_int), (void*) &Mat_A_height);  
  230.     clSetKernelArg(kernel, 3,sizeof(cl_int), (void*) &Mat_B_width);  
  231.     clSetKernelArg(kernel, 4,sizeof(cl_int), (void*) &Mat_B_height);  
  232.     clSetKernelArg(kernel, 5,sizeof(cl_mem), (void*) &bufferA);  
  233.     clSetKernelArg(kernel, 6,sizeof(cl_mem), (void*) &bufferB);  
  234.   
  235.     //Set Local and global workgroup sizes  
  236.     size_t globalws[2]={Mat_A_width,Mat_B_height};  
  237.     size_t localws[2]={Mat_A_width,Mat_B_height};  
  238.   
  239.     //float strTime = clock();  
  240.     //Execte the kernel  
  241.     errNum = clEnqueueNDRangeKernel(commandQueue,kernel,2,NULL,globalws,localws,0,NULL,NULL);  
  242.     if(errNum !=CL_SUCCESS)  
  243.     {  
  244.         std::cerr<<"Faile to Execte the kernal.."<<std::endl;  
  245.         return NULL;  
  246.     }  
  247.   
  248.     errNum = clEnqueueReadBuffer(commandQueue,bufferC,CL_TRUE,0,Mat_B_height*Mat_A_width*sizeof(float),(void*)MatC,0,NULL,NULL);  
  249.   
  250.     std::cout<<"MatrixC:"<<Mat_A_width<<"X"<<Mat_B_height<<std::endl;  
  251.     for(int i =0; i< Mat_A_width*Mat_B_height; i++)  
  252.     {  
  253.         if((i != 0)&&(i%Mat_B_height == 0))  
  254.         {  
  255.             std::cout<<std::endl;  
  256.         }  
  257.   
  258.         std::cout<<MatC[i]<<"\t";  
  259.     }  
  260.     std::cout << std::endl;  
  261.     clReleaseKernel(kernel);  
  262. #else  
  263.     cl_kernel Trapsposekernel;  
  264.     cl_int blockSize =16;  
  265.   
  266.     if(Mat_A_width*Mat_A_height >1000)  
  267.     {  
  268.         Trapsposekernel = clCreateKernel(program,"MatrixTranspose",NULL);  
  269.         std::cout<<"CreateKernel in MatrixTranspose"<<std::endl;  
  270.         if(Trapsposekernel == NULL)  
  271.         {  
  272.             std::cerr<<"Faile to Create TrapsposeKernel."<< std::endl;  
  273.             return NULL;  
  274.         }  
  275.           
  276.         clSetKernelArg(Trapsposekernel, 0,sizeof(cl_mem), (void*) &bufferC);  
  277.         clSetKernelArg(Trapsposekernel, 1,sizeof(cl_mem), (void*) &bufferA);  
  278.         clSetKernelArg(Trapsposekernel, 2,sizeof(cl_float)*blockSize*blockSize,NULL); //  
  279.         clSetKernelArg(Trapsposekernel, 3,sizeof(cl_int), (void*) &Mat_A_width);  
  280.         clSetKernelArg(Trapsposekernel, 4,sizeof(cl_int), (void*) &Mat_A_height);  
  281.         clSetKernelArg(Trapsposekernel, 5,sizeof(cl_mem), (void*) &blockSize);  //  
  282.     }  
  283.   
  284.     else  
  285.     {  
  286.         Trapsposekernel = clCreateKernel(program,"TrapsposeMatrixSample",NULL);  
  287.         std::cout<<"CreateKernel in TrapsposeMatrixSample"<<std::endl;  
  288.           
  289.         if(Trapsposekernel == NULL)  
  290.         {  
  291.             std::cerr<<"Faile to Create TrapsposeKernel."<< std::endl;  
  292.             return NULL;  
  293.         }  
  294.           
  295.         clSetKernelArg(Trapsposekernel, 0,sizeof(cl_mem), (void*) &bufferC);  
  296.         clSetKernelArg(Trapsposekernel, 1,sizeof(cl_int), (void*) &Mat_A_width);  
  297.         clSetKernelArg(Trapsposekernel, 2,sizeof(cl_int), (void*) &Mat_A_height);  
  298.         clSetKernelArg(Trapsposekernel, 3,sizeof(cl_mem), (void*) &bufferA);  
  299.     }  
  300.   
  301.     size_t localtr[2] = {Mat_A_height,Mat_A_width};  
  302. #ifdef MATRIXMULLTIPLY  
  303.     size_t globaltr[2] = {Mat_A_width,Mat_B_height}  
  304. #else  
  305.     size_t globaltr[2] = {Mat_A_height,Mat_A_width};  
  306. #endif //MATRIXMULLTIPLY  
  307.     cl_event  dev;  
  308.   
  309.     //commandQueue the kernel up for executio across the array  
  310.     errNum = clEnqueueNDRangeKernel(commandQueue,Trapsposekernel,2,NULL,globaltr,localtr,0,NULL,&dev);  
  311.     if(errNum !=CL_SUCCESS)  
  312.     {  
  313.         std::cerr<<"Faile to Execte the kernel.."<<std::endl;  
  314.         return NULL;  
  315.     }  
  316.   
  317.     std::cout<<"CommandQueue: "<<commandQueue<<std::endl;  
  318.     clFinish(commandQueue);  
  319.   
  320.     cl_ulong startTime, endTime;  
  321.     clGetEventProfilingInfo(dev, CL_PROFILING_COMMAND_START,sizeof(cl_ulong), &startTime, NULL);  
  322.     clGetEventProfilingInfo(dev, CL_PROFILING_COMMAND_END,  sizeof(cl_ulong), &endTime, NULL);  
  323.     cl_ulong kernelExecTimeNs = endTime-startTime;  
  324.     printf("simple kernal exec time :%8.6f ms\n", kernelExecTimeNs*1e-6 );  
  325.   
  326.     errNum = clEnqueueReadBuffer(commandQueue,bufferC,CL_TRUE,0,Mat_A_width*Mat_A_height*sizeof(float),(void*)MatC,0,NULL,NULL);  
  327.   
  328.     std::cout<<"====Trapspose MatrixA : "<<Mat_A_height<<"X"<<Mat_A_width<<std::endl;  
  329.     for(int i =0; i< Mat_A_width*Mat_A_height; i++)  
  330.     {  
  331.         if((i != 0)&&(i%Mat_A_width == 0))  
  332.         {  
  333.             std::cout<<std::endl;  
  334.         }  
  335.   
  336.         std::cout<<MatC[i]<<"\t";  
  337.     }  
  338.     std::cout << std::endl;  
  339.   
  340. #endif  
  341.   
  342.     clReleaseProgram(program);  
  343.     clReleaseCommandQueue(commandQueue);  
  344.     clReleaseContext(context);  
  345.   
  346.     delete[] MatA;  
  347.     //delete[] MatB;  
  348.     delete[] MatC;  
  349.   
  350.   
  351.     return 0;  
  352. }  

kernel代码

  1. /* 
  2.  *@param outputC output Matrix 
  3.  *@param widthA is width of intputA in the Matrix A 
  4.  *@param heightA is height of intputA in the Matrix A 
  5.  *@param widthB is width of intputB in the Matrix B 
  6.  *@param heightB is height of intputB in the Matrix B 
  7.  *@param inputA is width of intputA in the Matrix A 
  8.  *@param inputB is width of intputA in the Matrix B 
  9.  */  
  10. __kernel void MulltiplySample(__global float* outputC,  
  11.                         const int widthA,   
  12.                         const int heightA,  
  13.                         const int widthB,   
  14.                         const int heightB,   
  15.                         __global float* inputA,  
  16.                         __global float* inputB)  
  17. {  
  18.     int row = get_global_id(1); // Get global position in Y direction   
  19.     int col = get_global_id(0); // Get global position in X direction  
  20.   
  21.     float sum = 0.0f;  
  22.   
  23.     //Calculat result of one element of Matrix C  
  24.     forint i = 0; i< widthA; i++)  
  25.     {  
  26.         sum += inputA[row * widthA+i] * inputB[i * widthB + col];  
  27.     }  
  28.   
  29.     outputC[row * widthB+col] = sum;  
  30. }  
  31.   
  32. /* 
  33.  *@param TrapsposeMatrix  output Matrix 
  34.  *@param width  is InputMatrix width 
  35.  *@param height  is InputMatrix height 
  36.  *@param InputMatrix is Input Matrix 
  37.  */  
  38. __kernel void TrapsposeMatrixSample(__global float* TrapsposeMatrix,  
  39.                                     const uint width, const uint height,   
  40.                                     __global float* InputMatrix)  
  41. {  
  42.     int row = get_global_id(0);  
  43.     int col = get_global_id(1);  
  44.   
  45.     TrapsposeMatrix[row * width +col] = InputMatrix[col * height + row];  
  46. }  
  47.   
  48. /* 
  49.  * Copies a block to the local memory  
  50.  * and copies back the transpose from local memory to output 
  51.  * @param output output matrix 
  52.  * @param input  input matrix 
  53.  * @param block  local memory of size blockSize x blockSize 
  54.  * @param width  width of the input matrix 
  55.  * @param height height of the input matrix 
  56.  * @param blockSize size of the block 
  57.  */  
  58.   
  59. __kernel void MatrixTranspose(__global float * output,  
  60.                               __global float * input,  
  61.                               __local  float * block,  
  62.                               const    uint    width,  
  63.                               const    uint    height,  
  64.                               const    uint blockSize)  
  65. {  
  66.     uint globalIdx = get_global_id(0);  
  67.     uint globalIdy = get_global_id(1);  
  68.       
  69.     uint localIdx = get_local_id(0);  
  70.     uint localIdy = get_local_id(1);  
  71.       
  72.     /* copy from input to local memory */  
  73.     block[localIdy*blockSize + localIdx] = input[globalIdy*width + globalIdx];  
  74.   
  75.     /* wait until the whole block is filled */  
  76.     barrier(CLK_LOCAL_MEM_FENCE);  
  77.   
  78.     uint groupIdx = get_group_id(0);  
  79.     uint groupIdy = get_group_id(1);  
  80.   
  81.     /* calculate the corresponding target location for transpose  by inverting x and y values*/  
  82.     uint targetGlobalIdx = groupIdy*blockSize + localIdy;  
  83.     uint targetGlobalIdy = groupIdx*blockSize + localIdx;  
  84.   
  85.     /* calculate the corresponding raster indices of source and target */  
  86.     uint targetIndex  = targetGlobalIdy*height     + targetGlobalIdx;  
  87.     uint sourceIndex  = localIdy       * blockSize + localIdx;  
  88.       
  89.     output[targetIndex] = block[sourceIndex];  
  90. }  

测试结果输出

完整代码二:

maincpp代码

  1. // Matrix.cpp : Defines the entry point for the console application.  
  2.   
  3. #include "stdafx.h"  
  4. #include <CL/cl.h>  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <time.h>  
  8. #include <iostream>  
  9. #include <fstream>  
  10.   
  11. using namespace std;  
  12. #pragma comment (lib,"OpenCL.lib")  
  13.   
  14. #define M 2048  
  15.   
  16. int convertToString(const char *filename, std::string& s)  
  17. {  
  18.     size_t size;  
  19.     char*  str;  
  20.   
  21.     std::fstream f(filename, (std::fstream::in | std::fstream::binary));  
  22.     if(f.is_open())  
  23.     {  
  24.         size_t fileSize;  
  25.         f.seekg(0, std::fstream::end);  
  26.         size = fileSize = (size_t)f.tellg();  
  27.         f.seekg(0, std::fstream::beg);  
  28.   
  29.         str = new char[size+1];  
  30.         if(!str)  
  31.         {  
  32.             f.close();  
  33.             return NULL;  
  34.         }  
  35.   
  36.         f.read(str, fileSize);  
  37.         f.close();  
  38.         str[size] = '\0';  
  39.   
  40.         s = str;  
  41.         delete[] str;  
  42.         return 0;  
  43.     }  
  44.     printf("Error: Failed to open file %s\n", filename);  
  45.     return 1;  
  46. }  
  47.   
  48. int main(int argc, char* argv[])  
  49. {  
  50.     float *src1=0;  
  51.     float *src2=0;  
  52.   
  53.     src1 = (float*)malloc(M*M*sizeof(float));  
  54.     src2 = (float*)malloc(M*M*sizeof(float));  
  55.   
  56.     int i, j;  
  57.     srand( (unsigned)time( NULL ) );   
  58.     for(i = 0; i < M*M; i++)  
  59.         src1[i] = rand()%50;  
  60.   
  61.     for( i=0; i < M; i++)  
  62.     {  
  63.         for(j=0; j < M; j++)  
  64.         {  
  65.             src2[i*M+j] = src1[j*M+i];  
  66.         }  
  67.     }  
  68.   
  69.     cl_uint status;  
  70.     cl_platform_id platform;  
  71.   
  72.     status = clGetPlatformIDs( 1, &platform, NULL );  
  73.     cl_device_id device;  
  74.   
  75.     clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL,1, &device,NULL);  
  76.     cl_context context = clCreateContext( NULL, 1,&device,NULL, NULL, NULL);  
  77.     cl_command_queue queue = clCreateCommandQueue( context,device,  
  78.         CL_QUEUE_PROFILING_ENABLE, NULL );  
  79.   
  80.     cl_mem clsrc1 = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,  
  81.         M*M*sizeof(cl_float),src1,NULL );  
  82.     cl_mem clsrc2 = clCreateBuffer( context,CL_MEM_WRITE_ONLY,  
  83.         M*M * sizeof(cl_float), NULL, NULL );  
  84.   
  85.     const char * filename  = "transpose.cl";  
  86.     std::string  sourceStr;  
  87.     status = convertToString(filename, sourceStr);  
  88.     const char * source    = sourceStr.c_str();  
  89.     size_t sourceSize[]    = { strlen(source) };  
  90.   
  91.     cl_program program = clCreateProgramWithSource(context, 1, &source,sourceSize,NULL);  
  92.   
  93.     status = clBuildProgram( program, 1, &device, NULL, NULL, NULL );  
  94.     if(status != 0)  
  95.     {  
  96.         printf("clBuild failed:%d\n", status);  
  97.         char tbuf[0x10000];  
  98.         clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0x10000, tbuf, NULL);  
  99.         printf("\n%s\n", tbuf);  
  100.         return -1;  
  101.     }  
  102.   
  103.     cl_kernel kernel = clCreateKernel( program, "matrixTransposeSimple", NULL );  
  104.     cl_int dimx = M;  
  105.     cl_int dimy = M;  
  106.   
  107.     clSetKernelArg(kernel, 0, sizeof(cl_mem),  (void *)&clsrc2);  
  108.     clSetKernelArg(kernel, 1, sizeof(cl_mem),  (void *)&clsrc1);  
  109.     clSetKernelArg(kernel, 2, sizeof(cl_int),  (void *)&dimx);  
  110.     clSetKernelArg(kernel, 3, sizeof(cl_int),  (void *)&dimy);  
  111.   
  112.     //Set local and global workgroup sizes  
  113.     size_t localws[2] = {16, 16} ;   
  114.     size_t globalws[2] = {M,M};  
  115.   
  116.     cl_event ev;  
  117.     clEnqueueNDRangeKernel( queue ,kernel,2, 0, globalws, localws,0, NULL, &ev);  
  118.     clFinish( queue );  
  119.   
  120.     cl_ulong startTime, endTime;  
  121.     clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_START,sizeof(cl_ulong), &startTime, NULL);  
  122.     clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_END,sizeof(cl_ulong), &endTime, NULL);  
  123.     cl_ulong kernelExecTimeNs = endTime-startTime;  
  124.     printf("simple kernal exec time :%8.6f ms\n ", kernelExecTimeNs*1e-6 );  
  125.   
  126.     float *op_data = 0;  
  127.     // copy results from device back to host  
  128.     op_data = (cl_float *) clEnqueueMapBuffer(queue,clsrc2,CL_TRUE, CL_MAP_READ,0,   
  129.         M*M*sizeof(cl_float),0, NULL, NULL, NULL );  
  130.   
  131.     for(i = 0; i < M*M; i++)  
  132.     {  
  133.         if(abs(src2[i] - op_data[i]) > 0.0001)  
  134.         {  
  135.             printf("check failed\n");  
  136.             break;  
  137.         }  
  138.     }     
  139.     if(i == M*M)  
  140.         printf("check passed\n");  
  141.   
  142.     cl_uint blockSize = 16;  
  143.     kernel = clCreateKernel( program, "matrixTranspose", NULL );  
  144.   
  145.     clSetKernelArg(kernel, 0, sizeof(cl_mem),  (void *)&clsrc2);   
  146.     clSetKernelArg(kernel, 1, sizeof(cl_mem),  (void *)&clsrc1);   
  147.     clSetKernelArg(kernel, 2, sizeof(cl_float)*blockSize*blockSize, NULL);  
  148.     clSetKernelArg(kernel, 3, sizeof(cl_int),  (void *)&dimx);  
  149.     clSetKernelArg(kernel, 4, sizeof(cl_int),  (void *)&dimy);  
  150.     clSetKernelArg(kernel, 5, sizeof(cl_int),  (void *)&blockSize);  
  151.   
  152.     clEnqueueNDRangeKernel(queue ,kernel,2, 0, globalws, localws,0, NULL, &ev);  
  153.   
  154.     clFinish( queue );  
  155.     clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &startTime, NULL);  
  156.     clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_END,sizeof(cl_ulong), &endTime, NULL);  
  157.     kernelExecTimeNs = endTime-startTime;  
  158.     printf("kernal exec time :%8.6f ms\n ", kernelExecTimeNs*1e-6 );  
  159.   
  160.     // copy results from device back to host  
  161.     op_data = (cl_float *) clEnqueueMapBuffer( queue,clsrc2,CL_TRUE,CL_MAP_READ,0,    
  162.         M*M*sizeof(cl_float),0, NULL, NULL, NULL );  
  163.   
  164.     for(i = 0; i < M*M; i++)  
  165.     {  
  166.         if(abs(src2[i] - op_data[i]) > 0.0001)  
  167.         {  
  168.             printf("check failed\n");  
  169.             break;  
  170.         }  
  171.     }     
  172.     if(i == M*M)  
  173.         printf("check passed\n");  
  174.   
  175.     if(src1)  
  176.         free(src1);  
  177.     if(src2)  
  178.         free(src2);  
  179.   
  180.     clReleaseMemObject(clsrc1);   
  181.     clReleaseMemObject(clsrc2);  
  182.     clReleaseProgram(program);  
  183.     clReleaseCommandQueue(queue);  
  184.     clReleaseContext(context);  
  185.     return 0;  
  186. }  

kernel代码

  1. /* 
  2.  * Copies a block to the local memory  
  3.  * and copies back the transpose from local memory to output 
  4.  * @param output output matrix 
  5.  * @param input  input matrix 
  6.  * @param block  local memory of size blockSize x blockSize 
  7.  * @param width  width of the input matrix 
  8.  * @param height height of the input matrix 
  9.  * @param blockSize size of the block 
  10.  */  
  11.   
  12. __kernel   
  13. void matrixTranspose(__global float * output,  
  14.                      __global float * input,  
  15.                      __local  float * block,  
  16.                      const    uint    width,  
  17.                      const    uint    height,  
  18.                      const    uint blockSize  
  19.                        )  
  20. {  
  21.     uint globalIdx = get_global_id(0);  
  22.     uint globalIdy = get_global_id(1);  
  23.       
  24.     uint localIdx = get_local_id(0);  
  25.     uint localIdy = get_local_id(1);  
  26.       
  27.     /* copy from input to local memory */  
  28.     block[localIdy*blockSize + localIdx] = input[globalIdy*width + globalIdx];  
  29.   
  30.     /* wait until the whole block is filled */  
  31.     barrier(CLK_LOCAL_MEM_FENCE);  
  32.   
  33.     uint groupIdx = get_group_id(0);  
  34.     uint groupIdy = get_group_id(1);  
  35.   
  36.     /* calculate the corresponding target location for transpose  by inverting x and y values*/  
  37.     uint targetGlobalIdx = groupIdy*blockSize + localIdy;  
  38.     uint targetGlobalIdy = groupIdx*blockSize + localIdx;  
  39.   
  40.     /* calculate the corresponding raster indices of source and target */  
  41.     uint targetIndex  = targetGlobalIdy*height     + targetGlobalIdx;  
  42.     uint sourceIndex  = localIdy       * blockSize + localIdx;  
  43.       
  44.     output[targetIndex] = block[sourceIndex];  
  45. }  
  46.   
  47. __kernel void matrixTransposeSimple(__global float * output,  
  48.                      __global float * input,  
  49.                      const    uint    width,  
  50.                      const    uint    height  
  51.                        )  
  52. {  
  53.     uint gdx = get_global_id(0);  
  54.     uint gdy = get_global_id(1);  
  55.     output[gdy*width+gdx] = input[gdx*height+gdy] ;  
  56. }  

测试结果输出



敬请关注本博客和新浪微博songzi_tea.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值