MapReduce two parts:
Mapping: generating key-value pairs
Merge: deal with these key-value pairs
// kernel __kernel void string_search(char16 pattern, __global char* text, int chars_per_item, __local int* local_result, __global int* global_result) { char16 text_vector, check_vector; /* initialize local data */ local_result[0] = 0; local_result[1] = 0; local_result[2] = 0; local_result[3] = 0; / * The Make Sure Processing Previous has Completed * / Barrier (CLK_LOCAL_MEM_FENCE); // locally synchronous int item_offset = get_global_id ( 0 ) * chars_per_item; // the global id × size of each processed data de / * the Iterate through characters in text * / // iterate the process de data for ( int I = item_offset; I <item_offset + chars_per_item; I ++ ) { / * Load text INTO Private Global Buffer * / text_vector = vload16 ( 0 , text + I); / * and the Vector pattern text the Compare * / check_vector= text_vector == pattern; /* Check for 'that' */ if(all(check_vector.s0123)) atomic_inc(local_result); //原子操作 /* Check for 'with' */ if(all(check_vector.s4567)) atomic_inc(local_result + 1); /* Check for 'have' */ if(all(check_vector.s89AB)) atomic_inc(local_result + 2); /* Check for 'from' */ if(all(check_vector.sCDEF)) atomic_inc(local_result + 3); } /* Make sure local processing has completed */ barrier(CLK_GLOBAL_MEM_FENCE); // 全局同步 /* Perform global reduction */ if(get_local_id(0) == 0) { //归并 atomic_add(global_result, local_result[0]); //原子操作 atomic_add(global_result + 1, local_result[1]); atomic_add(global_result + 2, local_result[2]); atomic_add(global_result + 3, local_result[3]); } }
#define _CRT_SECURE_NO_WARNINGS #define PROGRAM_FILE "string_search.cl" #define KERNEL_FUNC "string_search" #define TEXT_FILE "kafka.txt" #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef MAC #include <OpenCL/cl.h> #else #include <CL/cl.h> #endif int main() { /* Host/device data structures */ cl_platform_id platform; cl_device_id device; cl_context context; cl_command_queue queue; cl_int err; /* Program/kernel data structures */ cl_program program; FILE *program_handle; char *program_buffer, *program_log; size_t program_size, log_size; cl_kernel kernel; size_t offset = 0; size_t global_size, local_size; // 全局大小 和局部大小 /* Data and buffers */ char pattern[16] = "thatwithhavefrom"; FILE *text_handle; char *text; size_t text_size; int chars_per_item;//每个item 的大小 int result[4] = {0, 0, 0, 0}; cl_mem text_buffer, result_buffer; /* Identify a platform */ // 获取平台 err = clGetPlatformIDs(1, &platform, NULL); if(err < 0) { perror("Couldn't identify a platform"); exit(1); } /* Access a device */ //Acquisition device ERR = clGetDeviceIDs (Platform, CL_DEVICE_TYPE_GPU, . 1 , & Device, NULL); IF (ERR < 0 ) { perror ( " Could Not the any Access Devices " ); Exit ( . 1 ); } / * the Determine size Global and local size * / // determined, and the overall size of the local size // CL_DEVICE_MAX_COMPUTE_UNITS obtained number calculation unit (CU) OpcnCL apparatus clGetDeviceInfo (device, CL_DEVICE_MAX_COMPUTE_UNITS, the sizeof (global_size), & global_size, NULL); // CL_DEVICE_MAX_WORK_GROUP_SIZE work items workgroup de quantitative restrictions clGetDeviceInfo (Device, CL_DEVICE_MAX_WORK_GROUP_SIZE, the sizeof (local_size), & local_size, NULL); // working global size × the number of each CU size workgroup global_size * = local_size; / * the Create A context * / context = clCreateContext (NULL, . 1 , & Device, NULL, NULL, & ERR); IF (ERR < 0 ) { perror ( " Could Not Create A context " ); Exit ( . 1 ); } / * the read File program and reading program Place Content INTO Buffer file * / program_handle= fopen(PROGRAM_FILE, "r"); if(program_handle == NULL) { perror("Couldn't find the program file"); exit(1); } fseek(program_handle, 0, SEEK_END); program_size = ftell(program_handle); rewind(program_handle); program_buffer = (char*)calloc(program_size+1, sizeof(char)); fread(program_buffer, sizeof(char), program_size, program_handle); fclose(program_handle); /* Read text file and place content into buffer 读取文本文件*/ text_handle = fopen(TEXT_FILE, "r"); if(text_handle == NULL) { perror("Couldn't find the text file"); exit(1); } fseek(text_handle, 0, SEEK_END); text_size = ftell(text_handle)-1; rewind(text_handle); text = (char*)calloc(text_size, the sizeof ( char )); fread (text, the sizeof ( char ), text_size, text_handle); fclose (text_handle); chars_per_item = text_size / global_size + . 1 ; // Text consignment oh ah / global size calculated for each item the data size / * the Create Program from File * / Program = clCreateProgramWithSource (context, . 1 , ( const char **) & program_buffer, & program_size, & ERR); IF (ERR < 0 ) { perror ( " Could Not Create the Program"); exit(1); } free(program_buffer); /* Build program */ err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL); if(err < 0) { /* Find size of log and print to std output */ clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); program_log = (char*) calloc(log_size+1, sizeof(char)); clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size+1, program_log, NULL); printf("%s\n", program_log); free(program_log); exit(1); } /* Create a kernel 创建核*/ kernel = clCreateKernel(program, KERNEL_FUNC, &err); if(err < 0) { perror("Couldn't create a kernel"); exit(1); }; /* Create buffers to hold the text characters and count */ // 文本 text_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, text_size, text, &err); if(err < 0) { perror("Couldn't create a buffer"); exit(1); }; // 全局结果 result_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(result), result, NULL); /* Create kernel argument */ err ClSetKernelArg = (Kernel, 0 , the sizeof (pattern), pattern); // mode entry ERR | = clSetKernelArg (Kernel, . 1 , the sizeof (cl_mem), & text_buffer); // Text ERR | = clSetKernelArg (Kernel, 2 , the sizeof ( chars_per_item), & chars_per_item); // for each size of the data entry process ERR | = clSetKernelArg (Kernel, . 3 , . 4 * the sizeof ( int ), NULL); // local size of the result ERR | = clSetKernelArg (Kernel, . 4 , the sizeof (cl_mem), & result_buffer); //全局结果 if(err < 0) { printf("Couldn't set a kernel argument"); exit(1); }; /* Create a command queue */ queue = clCreateCommandQueue(context, device, 0, &err); if(err < 0) { perror("Couldn't create a command queue"); exit(1); }; /* Enqueue kernel */ /** * cl_int clEnqueueNDRangeKernel ( cl_command_queue command_queue, // command queue cl_kernel kernel, // nuclear cl_uint work_dim, dimension data // const size_t * global_work_offset, // global ID offset in each dimension const size_t * global_work_size, // work items on each dimension number const size_t * local_work_size, on // the dimensions of a working group the number of work items cl_uint num_events_in_wait_list, const cl_event * event_wait_list, cl_event * Event ) * * * / ERR = clEnqueueNDRangeKernel (Queue, Kernel, . 1 , & offset, & global_size, local_size &, 0 , NULL, NULL); IF(err < 0) { perror("Couldn't enqueue the kernel"); printf("Error code: %d\n", err); exit(1); } /* Read and print the result */ // 读取数据命令 err = clEnqueueReadBuffer(queue, result_buffer, CL_TRUE, 0, sizeof(result), &result, 0, NULL, NULL); if(err < 0) { perror("Couldn't read the buffer"); exit(1); } printf("\nResults: \n"); printf("Number of occurrences of 'that': %d\n", result[0]); printf("Number of occurrences of 'with': %d\n", result[1]); printf("Number of occurrences of 'have': %d\n", result[2]); printf("Number of occurrences of 'from': %d\n", result[3]); /* Deallocate resources */ clReleaseMemObject (result_buffer); clReleaseMemObject (text_buffer); // release cached object clReleaseKernel (Kernel); // release core clReleaseCommandQueue (Queue); // release command queue clReleaseProgram (Program); // release procedure clReleaseContext (context); // releasing the context return 0 ; }