简体   繁体   English

启用OpenCL后无法在Magick ++中使用GPU

[英]Can't use GPU in Magick++ after enabling OpenCL

I wanted to use GPU in Magick++ functions of my project. 我想在我的项目的Magick ++函数中使用GPU。 I've built ImageMagick using this tutorial (OpenCL enabled). 我已经使用教程(启用OpenCL)构建了ImageMagick。 The convert.exe file after the built says that OpenCL is enabled. 生成后的convert.exe文件说已启用OpenCL。 I've included the necessary headers and libs (CORE_RL_Magick++_.lib, CORE_RL_MagickCore_.lib, CORE_RL_MagickWand_.lib). 我已经包含了必要的标头和库(CORE_RL_Magick ++ _。lib,CORE_RL_MagickCore_.lib,CORE_RL_MagickWand_.lib)。 I've also set a IMAGEMAGICK_OPENCL_CACHE_DIR system variable with a path (to store the necessary file). 我还设置了IMAGEMAGICK_OPENCL_CACHE_DIR系统变量和路径(用于存储必要的文件)。 I'm using Windows and Visual Studio. 我正在使用Windows和Visual Studio。
This is my code: 这是我的代码:

...
#include <Magick++.h>
#include <MagickCore/MagickCore.h>
#include <MagickWand/MagickWand.h>
#include <MagickCore\accelerate-private.h>
...

using namespace Magick;

int main(int argc, char *argv[])
{
    EnableOpenCL();
    InitializeMagick(NULL);
    EnableOpenCL(); // Executed this after InitializeMagick too to be sure. Maybe it's needed to be executed after InitializeMagick().

    Image img;
    img.read("F:/tmp/test/22/7.png");

    // These two functions should use GPU. But they don't. :
    img.gaussianBlur(15, 3);
    img.edge();
}

The code gives no errors but as you can see my code has functions that ImageMagick can use GPU in them. 该代码没有错误,但是如您所见,我的代码具有ImageMagick可以在其中使用GPU的功能。 But it does not. 但事实并非如此。 It only uses CPU. 它仅使用CPU。 Also, ImageMagick generates no files in the path set by IMAGEMAGICK_OPENCL_CACHE_DIR. 另外,ImageMagick在IMAGEMAGICK_OPENCL_CACHE_DIR设置的路径中不生成任何文件。
What part of it is wrong? 哪一部分错了?

Edit: 编辑:

C:\Users\User1>convert -version
Version: ImageMagick 7.0.8-4 Q16 x64 2018-06-29 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2018 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Visual C++: 190024210
Features: Cipher DPC HDRI Modules OpenCL OpenMP
Delegates (built-in): bzlib cairo flif freetype gslib heic jng jp2 jpeg lcms lqr lzma openexr pangocairo png ps raw rsvg tiff webp xml zlib

Also, my GPU supports OpenCL. 另外,我的GPU支持OpenCL。

Updated Answer 更新的答案

If setting MAGICK_OCL_DEVICE has no effect, and/or EnableOpenCl returns false , then OpenCL kernels can not be loaded one the targeted platform/device. 如果设置MAGICK_OCL_DEVICE无效,和/或EnableOpenCl返回false ,则无法将OpenCL内核加载到目标平台/设备中。 The behavior of ImageMagick is to emit a DelegateWarning (not error), and fail-back to the CPU. ImageMagick的行为是发出DelegateWarning (不是错误),然后故障回复到CPU。

I suspect that this is the case, and that the reasons why are logged to file named magick_badcl_build.log , and the actual OpenCL code that failed is written to magick_badcl.cl . 我怀疑是这种情况,那为什么会被记录到文件中指定的原因magick_badcl_build.log失败,而实际的OpenCL代码被写入magick_badcl.cl Both files should be posted to the developer forums for review. 这两个文件都应发布到开发者论坛进行审查。

Also, the environment variable should be MAGICK_OPENCL_CACHE_DIR , not IMAGEMAGICK_OPENCL_CACHE_DIR . 另外,环境变量应该是MAGICK_OPENCL_CACHE_DIR ,而不是IMAGEMAGICK_OPENCL_CACHE_DIR I think the documentation is wrong. 我认为文档是错误的。

From opencl.c 从opencl.c

  home=GetEnvironmentValue("MAGICK_OPENCL_CACHE_DIR"); if (home == (char *) NULL) { home=GetEnvironmentValue("XDG_CACHE_HOME"); if (home == (char *) NULL) home=GetEnvironmentValue("LOCALAPPDATA"); if (home == (char *) NULL) home=GetEnvironmentValue("APPDATA"); if (home == (char *) NULL) home=GetEnvironmentValue("USERPROFILE"); } 

Original Answer 原始答案

Use the method InitImageMagickOpenCL to control the OpenCL device management, not EnableOpenCl (which will auto select the best device, and the best device is usually the CPU). 使用方法InitImageMagickOpenCL来控制OpenCL设备管理,而不是EnableOpenCl (它将自动选择最佳设备,并且最佳设备通常是CPU)来控制OpenCL。

cl_uint platformCount;
cl_platform_id platforms[4];
cl_uint deviceCount;
cl_device_id devices[8];
cl_device_id * user_selected_GPU = nullptr;
clGetPlatformIDs(4, platforms, &platformCount);
// Grap the first GPU off the first platform.
// !!! Check docs as this is a _very_ bad example. !!!
if (platformCount > 0) {
    clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_GPU, 8, devices, &deviceCount);
    if (deviceCount > 0) {
        user_selected_GPU = devices[0];
    }
}
if (user_selected_GPU) {
    MagickCore::ExceptionInfo * exception = MagickCore::AcquireExceptionInfo();
    MagickCore::InitImageMagickOpenCL(
          MagickCore::MAGICK_OPENCL_DEVICE_SELECT_USER,
          user_selected_GPU,
          nullptr,
          exception
    );
} else {
    // No GPU found... 
}

Usually you won't need to bother defining what device to run on as ImageMagick will pull system & environment information. 通常,您无需费心定义要在哪个设备上运行,因为ImageMagick将获取系统和环境信息。 On my mac, for example, the CPU will always be selected out of the pool of devices. 例如,在我的Mac上,将始终从设备池中选择CPU。 If I would prefer to use GPU directly, I can define this at runtime with environment variables. 如果我想直接使用GPU,则可以在运行时使用环境变量定义它。

 MAGICK_OCL_DEVICE=GPU ./my_opencl_enabled_magick_application

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM