首页 > 解决方案 > 如何让 OpenCL 程序针对大型数据集运行?

问题描述

我是 OpenCL 的新手。我正在尝试在 NVIDIA GPU 上运行一个简单的 OpenCL 程序以进行矢量加法。

这是代码:

OpenCL 文件是:

#define MAX_SOURCE_SIZE (0x10000)

#include<stdio.h>
#include<stdlib.h> 
#include "CL/cl.h" 

int main()
{
  cl_uint ret_num_platforms;
  cl_uint ret_num_devices;
  cl_platform_id platform_id = NULL;
  cl_kernel kernel2 = NULL;
  cl_program program2 = NULL;
  cl_command_queue command_queue = NULL;
  cl_context context = NULL;
  cl_device_id device_id = NULL;
  cl_int ret;
  FILE * fp2;
  char fileName2[]="./kernel.cl";
  int for_var=0;
  char * source_str2;
  size_t source_size2;
  size_t globalWorkSize[1];
  size_t localWorkSize[1];
  cl_mem cl_buffer3;
  cl_mem cl_buffer2;
  cl_mem cl_buffer1;
  cl_mem cl_buffer0;
  int *A;
  int *B;
  int *C;
  int *n;
  int i;
  n = ((int *)(malloc((sizeof(int )))));
  printf("Enter the number of elements of vector : \n");
  scanf("%d",n);
  A = ((int *)(malloc((( *n) * sizeof(int )))));
  B = ((int *)(malloc((( *n) * sizeof(int )))));
  C = ((int *)(malloc((( *n) * sizeof(int )))));
  printf("\nInput Vector1 :\n");
  for (i = 0; i <=  *n - 1; i += 1) {
    A[i] = (2 * i);
    printf("%d ",A[i]);
  }
  printf("\n\nInput Vector2 :\n");
  for (i = 0; i <=  *n - 1; i += 1) {
    B[i] = (3 * i);
    printf("%d ",B[i]);
  }
  ret = clGetPlatformIDs(1,&platform_id,&ret_num_platforms);
  if (ret != CL_SUCCESS) {
    printf("Platform error");
  }
  ret = clGetDeviceIDs(platform_id,CL_DEVICE_TYPE_DEFAULT,1,&device_id,&ret_num_devices);
  if (ret != CL_SUCCESS)
  printf("device err");
  context=clCreateContext(NULL,1,&device_id,NULL,NULL,&ret);
  if (!context)
  printf("context err");
  command_queue = clCreateCommandQueue(context,device_id,0,&ret);
  if (!command_queue)
  printf("command queue error");
  localWorkSize[0] = 16;

  globalWorkSize[0] =16400;

  cl_buffer0=clCreateBuffer(context, CL_MEM_WRITE_ONLY, (*n) * sizeof(int), NULL, &ret);
  cl_buffer1=clCreateBuffer(context, CL_MEM_WRITE_ONLY, (*n) * sizeof(int), NULL, &ret);
  cl_buffer3=clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(int), NULL, &ret);
 cl_buffer2=clCreateBuffer(context, CL_MEM_READ_WRITE, (*n) * sizeof(int), NULL, &ret);
  ret = clEnqueueWriteBuffer(command_queue, cl_buffer0 , CL_TRUE, 0,(*n) * sizeof(int), A, 0, NULL, NULL);
  ret = clEnqueueWriteBuffer(command_queue, cl_buffer1 , CL_TRUE, 0,(*n) * sizeof(int), B, 0, NULL, NULL);
  ret = clEnqueueWriteBuffer(command_queue, cl_buffer3 , CL_TRUE, 0, sizeof(int), n, 0, NULL, NULL);
  ret = clEnqueueWriteBuffer(command_queue, cl_buffer2 , CL_TRUE, 0,(*n) * sizeof(int), C, 0, NULL, NULL);
  fp2 = fopen(fileName2,"r");
  if (!fp2) {
    fprintf(stderr,"Failed");
    exit(1);
  }
  source_str2 = (char*)malloc(MAX_SOURCE_SIZE);
  source_size2 = fread(source_str2,1,MAX_SOURCE_SIZE,fp2);
  fclose(fp2);
  program2 = clCreateProgramWithSource(context, 1, (const char **)&source_str2,(const size_t *)&source_size2, &ret);
  if(!program2)
  printf("error creating program2");
  ret = clBuildProgram(program2, 1, &device_id, NULL, NULL, NULL);
  if (ret)
  printf("error building program2");
  kernel2 = clCreateKernel(program2, "ADD" , &ret);
  ret = clSetKernelArg(kernel2, 0, sizeof(cl_mem), &cl_buffer0);
  ret = clSetKernelArg(kernel2, 1, sizeof(cl_mem), &cl_buffer1);
  ret = clSetKernelArg(kernel2, 2, sizeof(cl_mem), &cl_buffer2);
  ret = clSetKernelArg(kernel2, 3, sizeof(cl_mem), &cl_buffer3);
  ret = clEnqueueNDRangeKernel(command_queue, kernel2, 1, NULL, globalWorkSize, localWorkSize, 0 , NULL , NULL);
  ret = clEnqueueReadBuffer(command_queue, cl_buffer2 , CL_TRUE, 0,(*n) * sizeof(int), C, 0, NULL, NULL);
  printf("\n\nAddition of vectors :\n");
  for (i = 0; i <=  *n - 1; i += 1) {
    printf("%d ",C[i]);
  }
  clReleaseMemObject(cl_buffer0);
  clReleaseMemObject(cl_buffer1);
  clReleaseMemObject(cl_buffer2);
  clReleaseMemObject(cl_buffer3);
clReleaseCommandQueue(command_queue);
  clReleaseContext(context);
  return 0; 
}

内核文件是(kernel.cl):

__kernel void ADD(__constant int *A,__constant int *B,__global int *C,__constant int *n)
{
  int i = get_global_id(0);
  if (i <=  *n - 1) {
    C[i] = (A[i] + B[i]);
  }
}

如果我将 16384 作为总向量元素,则该程序可以正常工作,但是对于超过该值的值,它会给出 0 作为输出。我想用大数据集运行这个程序,以便我可以将它的性能与在 CPU 上运行的程序进行比较。

请指导我该怎么做?

标签: opencl

解决方案


您的代码中至少存在一个错误 - 您正在将MEM_SIZE * sizeof(int)字节复制n到缓冲区 3:

ret = clEnqueueWriteBuffer(command_queue, cl_buffer3 , CL_TRUE, 0,MEM_SIZE * sizeof(int), n, 0, NULL, NULL);

但是,n只有sizeof(int)字节长:

n = ((int *)(malloc((sizeof(int )))));

我不知道这可能会导致什么问题,而且完全有可能还有其他更严重的错误,但是这个肯定没有帮助。


推荐阅读