GraphicsMagick 的 OpenCL 开发记录(二十一)

发布时间:2024年01月24日

<2022-04-13 Wed>

支持windows平台

支持windows平台需要做的:

  1. GraphicsMagick/VisualMagick/configure/configure.exe增加“Enable OpenCL”多选框。
    在这里插入图片描述
  2. 从“VisualMagick”拷贝OpenCL/CL头文件。
  3. vs报错:error C2004: expected 'defined(id)',因为它不支持这样的语法:
#if defined(/*MAGICKCORE_OPENMP_SUPPORT*/HAVE_OPENMP)
  1. 一些函数的MagickExport得去掉,因为重定义。
  2. MAGICKCORE_WINDOWS_SUPPORT替换为MSWINDOWS

修改量较大,所有修改见commitbuild ok with opencl on Windows

<2022-04-14 周四>

windows平台不能生成内核的.bin文件

问题出在CacheOpenCLKernel()函数中:

static void CacheOpenCLKernel(MagickCLDevice device,char *filename,
  ExceptionInfo *exception)
{
  cl_uint
    status;

  size_t
    binaryProgramSize;

  unsigned char
    *binaryProgram;

  status=openCL_library->clGetProgramInfo(device->program,
    CL_PROGRAM_BINARY_SIZES,sizeof(size_t),&binaryProgramSize,NULL);
  if (status != CL_SUCCESS)
    return;
  binaryProgram=(unsigned char*) AcquireQuantumMemory(1,binaryProgramSize);
  if (binaryProgram == (unsigned char *) NULL)
    {
      (void) ThrowException(exception,
        ResourceLimitError,MemoryAllocationFailed,"CacheOpenCLKernel");
      return;
    }
  status=openCL_library->clGetProgramInfo(device->program,
    CL_PROGRAM_BINARIES,sizeof(unsigned char*),&binaryProgram,NULL);
  if (status == CL_SUCCESS)
    {
      (void) LogMagickEvent(AccelerateEvent,GetMagickModule(),
        "Creating cache file: \"%s\"",filename);
      (void) BlobToFile(filename,binaryProgram,binaryProgramSize,exception);
    }
  binaryProgram=(unsigned char *) RelinquishMagickMemory(binaryProgram);
}

因为clGetProgramInfo()的返回值是-30对应CL_INVALID_VALUE错误,修改之后可以临时解决:

static void CacheOpenCLKernel(MagickCLDevice device, char* filename,
  ExceptionInfo* exception)
{
  cl_uint
    status;

  size_t
    * binaryProgramSize,
    num_binaries;

  unsigned char
    ** binaryProgram;

  status = openCL_library->clGetProgramInfo(device->program, CL_PROGRAM_BINARY_SIZES,
    0, 0, &num_binaries);
  if (status != CL_SUCCESS)
    return;
  num_binaries = num_binaries / sizeof(size_t);
  binaryProgramSize = (size_t*)malloc(num_binaries * sizeof(size_t));
  binaryProgram = (const unsigned char**)calloc(num_binaries, sizeof(unsigned char*));
  status = openCL_library->clGetProgramInfo(device->program,
    CL_PROGRAM_BINARY_SIZES, num_binaries * sizeof(size_t), binaryProgramSize, NULL);
  LogMagickEvent(AccelerateEvent, GetMagickModule(), "clGetProgramInfo return: %d", status);
  if (status != CL_SUCCESS)
    return;
  for (int i = 0; i < num_binaries; ++i) {
    if (binaryProgramSize[i]) {
      binaryProgram[i] = (unsigned char*)AcquireQuantumMemory(1, binaryProgramSize[i]);
      if (binaryProgram[i] == (unsigned char*)NULL)
      {
        (void)ThrowException(exception,
          ResourceLimitError, MemoryAllocationFailed, "CacheOpenCLKernel");
        return;
      }
      status = openCL_library->clGetProgramInfo(device->program,
        CL_PROGRAM_BINARIES, num_binaries * sizeof(unsigned char*), binaryProgram, NULL);
      if (status == CL_SUCCESS)
      {
        (void)LogMagickEvent(AccelerateEvent, GetMagickModule(),
          "Creating cache file: \"%s\"", filename);
        (void)BlobToFile(filename, binaryProgram[i], binaryProgramSize[i], exception);
      }
      binaryProgram = (unsigned char*)RelinquishMagickMemory(binaryProgram);
    }
  }
}

_aligned_free()free()不匹配的问题

windows平台下这个问题出现了,之前相同代码在linux上运行的很好。

经调查发现是因为在DestroyMagickCLCacheInfoAndPixels()函数中使用的是:

MagickFreeAlignedMemory(pixels);

来清除在pixel_cache.c:OpenCache()中由:

MagickReallocMemory(PixelPacket *,cache_info->pixels,(size_t) offset);

申请的内存,造成不匹配。

因此DestroyMagickCLCacheInfoAndPixels()中改为MagickFreeMemory()来释放内存。这里的做法不同于ImageMagick,在GraphicsMagick中未使用对齐的内存,就像pixel_cache.c:DestroyCacheInfo()那样释放内存一样,才不会出问题。

  /*
    Release Cache Pixel Resources
  */
  if (MemoryCache == cache_info->type)
    {
#if defined(HAVE_OPENCL)
      if (cache_info->opencl != (MagickCLCacheInfo) NULL)
        {
          cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
            MagickTrue);
          cache_info->pixels=(Quantum *) NULL;
        }
#else
      MagickFreeMemory(cache_info->pixels);
      LiberateMagickResource(MemoryResource,cache_info->length);
#endif
    }

OpenCL中不使用对齐内存对性能影响很大,这可以作为一个性能优化点。

此外MAGICKCORE_HAVE__ALIGNED_MALLOC宏应该被替换为HAVE__ALIGNED_MALLOC

文章来源:https://blog.csdn.net/ftuc5dn/article/details/135815952
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。