文章目录
- 支持`windows`平台
- `windows`平台不能生成内核的`.bin`文件
- `_aligned_free()`和`free()`不匹配的问题
<2022-04-13 Wed>
支持windows
平台
支持windows
平台需要做的:
- 为
GraphicsMagick/VisualMagick/configure/configure.exe
增加“Enable OpenCL”多选框。
- 从“VisualMagick”拷贝
OpenCL/CL
头文件。 vs
报错:error C2004: expected 'defined(id)'
,因为它不支持这样的语法:
#if defined(/*MAGICKCORE_OPENMP_SUPPORT*/HAVE_OPENMP)
- 一些函数的
MagickExport
得去掉,因为重定义。 MAGICKCORE_WINDOWS_SUPPORT
替换为MSWINDOWS
。
修改量较大,所有修改见commit
:build 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
。