【问题标题】:How to make an OpenCL program run for large data set?如何让 OpenCL 程序针对大型数据集运行?
【发布时间】:2019-03-15 05:25:55
【问题描述】:

我是 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 上运行的程序进行比较。

请指导我该怎么做?

【问题讨论】:

  • 您可以使用clGetDeviceInfo查询设备的最大本地和全局工作大小以查询CL_DEVICE_MAX_WORK_GROUP_SIZECL_DEVICE_MAX_WORK_ITEM_SIZES设备信息属性。 16 和 1024 通常应该没有问题。如果您的程序挂起,您的代码中可能还有其他错误。如果您需要帮助诊断问题,则需要发布一些代码。
  • 我在 NVIDIA Tesla M2050 上运行这个程序。在这里,CL_DEVICE_MAX_WORK_GROUP_SIZE 给出 1024,0,0,CL_DEVICE_MAX_WORK_ITEM_SIZES 给出 1024,1024,64

标签: opencl


【解决方案1】:

您的代码中至少存在一个错误 - 您正在将 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 )))));

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

【讨论】:

  • 谢谢@pmdj。我已经更新了代码。请看一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 2016-04-18
  • 2012-04-30
相关资源
最近更新 更多