了解 OpenCL 在 OpenCV 中的使用(Mat/Umat Objects)

Sur*_*ith 2 c++ performance opencv image-processing opencl

我运行下面的代码来检查 GPU 和 CPU 使用率之间的性能差异。我正在计算cv::cvtColor()函数的平均时间。我进行了四个函数调用:

  1. Just_mat()(不使用 OpenCLMat对象)
  2. Just_UMat()(不使用 OpenCLUmat对象)
  3. OpenCL_Mat()(对Mat对象使用 OpenCL )
  4. OpenCL_UMat()(对UMat对象使用 OpenCL )

适用于 CPU 和 GPU。
我没有发现 GPU 和 CPU 使用率之间存在巨大的性能差异。

int main(int argc, char* argv[])
{
    loc = argv[1];
    just_mat(loc);// Calling function Without OpenCL 
    just_umat(loc);//Calling function Without OpenCL 
    cv::ocl::Context context;
    std::vector<cv::ocl::PlatformInfo> platforms;
    cv::ocl::getPlatfomsInfo(platforms);
    for (size_t i = 0; i < platforms.size(); i++)
    {
        //Access to Platform
        const cv::ocl::PlatformInfo* platform = &platforms[i];

        //Platform Name
        std::cout << "Platform Name: " << platform->name().c_str() << "\n" << endl;

        //Access Device within Platform
        cv::ocl::Device current_device;
        for (int j = 0; j < platform->deviceNumber(); j++)
        {
            //Access Device
            platform->getDevice(current_device, j);
            int deviceType = current_device.type();
            cout << "Device name:  " << current_device.name() << endl;
            if (deviceType == 2)
                cout << context.ndevices() << " CPU devices are detected." << std::endl;
            if (deviceType == 4)
                cout << context.ndevices() << " GPU devices are detected." << std::endl;
            cout << "===============================================" << endl << endl;
            switch (deviceType) 
            {
            case (1 << 1):
                cout << "CPU device\n";
                if (context.create(deviceType))
                    opencl_mat(loc);//With OpenCL Mat
                break;
            case (1 << 2):
                cout << "GPU device\n";              
                if (context.create(deviceType))
                    opencl_mat(loc);//With OpenCL UMat
                break;
            }
            cin.ignore(1);
        }
    }
    return 0;
}
int just_mat(string loc);// I check for the average time taken for cvtColor() without using OpenCl
int just_umat(string loc);// I check for the average time taken for cvtColor() without using OpenCl
int opencl_mat(string loc);//ocl::setUseOpenCL(true); and check for time difference for cvtColor function
int opencl_umat(string loc);//ocl::setUseOpenCL(true); and check for time difference for cvtColor function
Run Code Online (Sandbox Code Playgroud)

上述代码的输出(以毫秒为单位)为
__________________________________________
|GPU 名称|使用 OpenCL Mat | 使用 OpenCl UMat|
|_________________________________________|
|--Carrizo---|------7.69052 ------ |------0.247069-------|
|_________________________________________|
|---岛--- |-------7.12455------ |------0.233345-------|
|_________________________________________|


__________________________________________
|----CPU---|使用OpenCL Mat | 使用 OpenCl UMat |
|_________________________________________|
|---AMD---|------6.76169 ------ |--------0.231103--------|
|_________________________________________|


________________________________________________
|----CPU---| 没有 OpenCL Mat | 没有 OpenCl UMat |
|_________________________________________________________|
|----AMD---|------7.15959------ |------------0.246138------------ |
|_________________________________________________________|

在代码中,无论代码如何,使用 Mat 对象始终在 CPU 上运行,而使用 UMat 对象始终在 GPU 上运行ocl::setUseOpenCL(true/false);
任何人都可以解释所有输出时间变化的原因吗?

还有一个问题,我没有使用任何 OpenCL 特定的 .dll 和 .exe 文件,但使用 GPU 没有任何错误,在使用 Cmake 构建 OpenCV 时,我检查With_OpenCL了这是否构建了所有 OpenCL 所需的功能opencv_World310.dll

Bia*_*int 5

在代码中,使用 Mat 对象总是在 CPU 上运行,而使用 UMat 对象总是在 GPU 上运行,而不管代码 ocl::setUseOpenCL(true/false);

对不起,因为我不确定这是一个问题还是一个陈述......在任何一种情况下它都是部分正确的。在 3.0 中,UMat如果您没有专用 GPU,那么 OpenCV 只会在 CPU 上运行所有内容。如果你特别要求Mat你把它放在 CPU 上。在您的情况下,您已经通过专门选择每个 GPU/CPU 来指示它们在每个 GPU/CPU 上运行(更多关于“选择下面的 CPU)...阅读此内容

很少有设计选择支持新架构:

  1. 一个统一的抽象 cv::UMat,可以使用 CPU 或 OpenCL 代码实现相同的 API,而无需显式调用 OpenCL 加速版本。如果系统中存在,这些函数使用支持 OpenCL 的 GPU,否则自动切换到 CPU 操作。

  2. UMat 抽象使函数能够被异步调用。与 OpenCV 2.x 版的 cv::Mat 不同,对 cv::UMat 的基础数据的访问是通过类的方法执行的,而不是通过其数据成员执行的。这种方法使实现能够仅在 CPU 代码绝对需要结果时才显式等待 GPU 完成。

  3. UMat 实现利用了 Intel SoC 上可用的 CPU-GPU 共享物理内存,包括来自传递到 OpenCV 的指针的分配。

我认为对“使用 OpenCL”也可能存在误解。当您使用 时UMat,您是在专门尝试使用 GPU。而且,我会在这里恳求一些无知,因此我相信 CV 正在使用一些 CL 库来自动实现......作为 2.X 的一面,我们有 cv::ocl 专门/手动做因此,如果您在 3.X 中使用该 2.X 遗留代码,请务必小心。这样做是有原因的,但它们并不总是直截了当的。但是,回到主题,当你说,

使用 OpenCL UMat

你可能是多余的。您在代码片段中的 CL 代码基本上是找出安装了哪些设备、有多少设备、它们的名称是什么以及选择使用哪个......我必须深入研究它的实例化方式,但也许当你UMat让它自动将 OpenCL 设置为 True 时?(链接)这肯定会支持您提供的数据。您可以通过在将 ocl::setUseOpenCL 设置为 false 然后使用UMat.

最后,我猜你的 CPU 有一个内置的 GPU。因此,它使用 OpenCL 运行并行处理,而不需要花费时间来往返于单独/专用 GPU 并返回,因此您感知到的性能优于 GPU(因为从技术上讲它不是运行它的 CPU)......只有当你专门使用的Mat是 CPU 只被使用。

你的最后一个问题,我不确定......这是我的猜测:OpenCL 架构存在于 GPU 上,当你使用 CL 安装 CV 时,你正在安装两个库和相关头文件之间的链接。我不确定您需要哪些 dll 文件才能实现这种魔力。