我的机器上 OpenCV 算法的 GPU 版本比 CPU 版本慢?

2023-12-02

在尝试使用 GPU 和 OpenCV 来加速简单算法时,我注意到在我的机器(Ubuntu 12.10、NVidia 9800GT、Cuda 4.2.9、g++ 4.7.2)上,GPU 版本实际上比 CPU 版本慢。我用下面的代码进行了测试。

#include <opencv2/opencv.hpp>
#include <opencv2/gpu/gpu.hpp>

#include <chrono>
#include <iostream>

int main()
{
    using namespace cv;
    using namespace std;

    Mat img1(512, 512, CV_32FC3, Scalar(0.1f, 0.2f, 0.3f));
    Mat img2(128, 128, CV_32FC3, Scalar(0.2f, 0.3f, 0.4f));
    Mat img3(128, 128, CV_32FC3, Scalar(0.3f, 0.4f, 0.5f));

    auto startCPU = chrono::high_resolution_clock::now();
    double resultCPU(0.0);
    cout << "CPU ... " << flush;
    for (int y(0); y < img2.rows; ++y)
    {
        for (int x(0); x < img2.cols; ++x)
        {
            Mat roi(img1(Rect(x, y, img2.cols, img2.rows)));
            Mat diff;
            absdiff(roi, img2, diff);
            Mat diffMult(diff.mul(img3));
            Scalar diffSum(sum(diff));
            double diffVal(diffSum[0] + diffSum[1] + diffSum[2]);
            resultCPU += diffVal;
        }
    }
    auto endCPU = chrono::high_resolution_clock::now();
    auto elapsedCPU = endCPU - startCPU;
    cout << "done. " << resultCPU << " - ticks: " << elapsedCPU.count() << endl;

    gpu::GpuMat img1GPU(img1);
    gpu::GpuMat img2GPU(img2);
    gpu::GpuMat img3GPU(img3);
    gpu::GpuMat diffGPU;
    gpu::GpuMat diffMultGPU;
    gpu::GpuMat sumBuf;

    double resultGPU(0.0);
    auto startGPU = chrono::high_resolution_clock::now();
    cout << "GPU ... " << flush;
    for (int y(0); y < img2GPU.rows; ++y)
    {
        for (int x(0); x < img2GPU.cols; ++x)
        {
            gpu::GpuMat roiGPU(img1GPU, Rect(x, y, img2GPU.cols, img2GPU.rows));
            gpu::absdiff(roiGPU, img2GPU, diffGPU);
            gpu::multiply(diffGPU, img3GPU, diffMultGPU);
            Scalar diffSum(gpu::sum(diffMultGPU, sumBuf));
            double diffVal(diffSum[0] + diffSum[1] + diffSum[2]);
            resultGPU += diffVal;
        }
    }
    auto endGPU = chrono::high_resolution_clock::now();
    auto elapsedGPU = endGPU - startGPU;
    cout << "done. " << resultGPU << " - ticks: " << elapsedGPU.count() << endl;
}

我的结果如下:

CPU ... done. 8.05306e+07 - ticks: 4028470
GPU ... done. 3.22122e+07 - ticks: 5459935

如果这有帮助:我的探查器(System Profiler 1.1.8)告诉我,大部分时间都花在cudaDeviceSynchronize.

我使用 OpenCV GPU 函数的方式是否做错了一些基本的事情,或者我的 GPU 速度太慢?


感谢 hubs 和 Eric 的评论,我能够以 GPU 版本实际上变得比 CPU 版本更快的方式更改我的测试。导致两个版本校验和不同的错误现在也已消除。 ;-)

#include <opencv2/opencv.hpp>
#include <opencv2/gpu/gpu.hpp>

#include <chrono>
#include <iostream>

int main()
{
    using namespace cv;
    using namespace std;

    Mat img1(512, 512, CV_32FC3, Scalar(1.0f, 2.0f, 3.0f));
    Mat img2(128, 128, CV_32FC3, Scalar(4.0f, 5.0f, 6.0f));
    Mat img3(128, 128, CV_32FC3, Scalar(7.0f, 8.0f, 9.0f));
    Mat resultCPU(img2.rows, img2.cols, CV_32FC3, Scalar(0.0f, 0.0f, 0.0f));

    auto startCPU = chrono::high_resolution_clock::now();
    cout << "CPU ... " << flush;
    for (int y(0); y < img1.rows - img2.rows; ++y)
    {
        for (int x(0); x < img1.cols - img2.cols; ++x)
        {
            Mat roi(img1(Rect(x, y, img2.cols, img2.rows)));
            Mat diff;
            absdiff(roi, img2, diff);
            Mat diffMult(diff.mul(img3));
            resultCPU += diffMult;
        }
    }
    auto endCPU = chrono::high_resolution_clock::now();
    auto elapsedCPU = endCPU - startCPU;
    Scalar meanCPU(mean(resultCPU));
    cout << "done. " << meanCPU << " - ticks: " << elapsedCPU.count() << endl;

    gpu::GpuMat img1GPU(img1);
    gpu::GpuMat img2GPU(img2);
    gpu::GpuMat img3GPU(img3);
    gpu::GpuMat diffGPU(img2.rows, img2.cols, CV_32FC3);
    gpu::GpuMat diffMultGPU(img2.rows, img2.cols, CV_32FC3);
    gpu::GpuMat resultGPU(img2.rows, img2.cols, CV_32FC3, Scalar(0.0f, 0.0f, 0.0f));

    auto startGPU = chrono::high_resolution_clock::now();
    cout << "GPU ... " << flush;
    for (int y(0); y < img1GPU.rows - img2GPU.rows; ++y)
    {
        for (int x(0); x < img1GPU.cols - img2GPU.cols; ++x)
        {
            gpu::GpuMat roiGPU(img1GPU, Rect(x, y, img2GPU.cols, img2GPU.rows));
            gpu::absdiff(roiGPU, img2GPU, diffGPU);
            gpu::multiply(diffGPU, img3GPU, diffMultGPU);
            gpu::add(resultGPU, diffMultGPU, resultGPU);
        }
    }
    auto endGPU = chrono::high_resolution_clock::now();
    auto elapsedGPU = endGPU - startGPU;
    Mat downloadedResultGPU(resultGPU);
    Scalar meanGPU(mean(downloadedResultGPU));
    cout << "done. " << meanGPU << " - ticks: " << elapsedGPU.count() << endl;
}

Output:

CPU ... done. [3.09658e+06, 3.53894e+06, 3.98131e+06, 0] - ticks: 34021332
GPU ... done. [3.09658e+06, 3.53894e+06, 3.98131e+06, 0] - ticks: 20609880

这不是我预期的加速,但可能我的 GPU 并不是最适合这个东西的。多谢你们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我的机器上 OpenCV 算法的 GPU 版本比 CPU 版本慢? 的相关文章

  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 可空属性与可空局部变量

    我对以下行为感到困惑Nullable types class TestClass public int value 0 TestClass test new TestClass Now Nullable GetUnderlyingType
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr

随机推荐

  • Python input() 函数中的 NameError [重复]

    这个问题在这里已经有答案了 input var input Press E and Enter to Exit NameError name e is not defined 我正在使用Python 2 5 我怎样才能克服这个错误 inpu
  • 解释用于获取文件名的 linux 正则表达式

    任何人都可以帮助我解释为什么使用这种方式获取文件名 例如 该文件是 fileName Users test am01 output output log fileName fileName 然后我们得到 fileName output lo
  • 在 MS Chart 的缩放视图上获取点

    我正在使用 Microsoft Chart 控件并允许用户选择 我希望能够在用户选择要缩放的区域后获取当前缩放 查看 区域的数据点 关于如何做到这一点有什么想法吗 我正在使用 Net 4 5 这是发送当前可见的示例DataPoints到控制
  • 打印 char 的二进制格式

    我写了一个函数来打印a的二进制格式char几个月前 它是这样的并且运行良好 void PrnCharBit char x int i mask for i CHAR BIT i gt 1 i mask 1 lt lt i 1 x putch
  • 文件未找到异常 IIS7

    我有一个 C Web 应用程序 在 VS2010 中运行得非常好 但是当部署到 IIS7 服务器时 返回 图像未找到图标 这段代码本质上是抓取网络共享位置上图像的缩略图 进行操作 然后推送回网页 Web 服务器与其尝试访问的文件位于同一网络
  • PHP json_encode - 奇怪的行为

    Using json encode对日期数组进行编码 它有时会做一件事 有时会做另一件事 例如 如果我尝试编码如下内容 array 6 0 gt string 6 Jun 24 1 gt string 6 Jun 25 2 gt strin
  • 如何将“4000万”转换为40,000,000美元?

    我正在寻找一种方法将数字字符串 如主题中所示 转换为正确的字符串 例如 40 000 000 php 是否提供了执行此操作的函数 谢谢您的帮助 str str replace billion 000000000 str str str re
  • 访问 Web 服务时出现 HTTP 403 错误

    我正在尝试从远程计算机访问网络服务 我设法从浏览器访问网络服务 但是当我尝试从应用程序调用 Web 服务时 我收到 HTTP 403 知道为什么吗 A 403响应表明您正在连接的主机或软件不允许访问 Web 服务 造成这种情况的原因可能是
  • 内联盒和原子内联盒的区别

    考虑以下代码 div div div display inline block div 块现在生成原子内联级框 正如中所述规格9 2 2 非行内框的行内级框 例如替换的 内联级元素 内联块元素和内联表 元素 被称为原子内联级框 因为它们 作
  • 剥离驱动器盘符

    通过使用 D 驱动器中文件夹中的命令 for f delims d in cd do set pathdrv d echo pathdrv 我得到 d 某个文件夹 我想编写批处理命令以在驱动器根目录中创建自动运行文件 请帮我删除驱动器号 d
  • 使用 SelectTokens 查询 JSON?使用 C# 中的 Newtonsoft.Json.Linq

    我试图在 C 中使用 Newtonsoft JSON Linq 来更改以下 JSON 中的 statusCode 值 disbursements id 1f337641 contactId f5eb2 statusCode 16600000
  • Node / Express:EADDRINUSE,地址已在使用中 - 终止服务器

    我有一个使用 connect 在 node js 中运行的简单服务器 var server require connect createServer actions server listen 3000 在我的代码中 我有实际的处理程序 但
  • 表有 2 个字段,但一次只能使用一个

    您将如何设计一个数据库 该数据库有一个包含 2 个字段的表 并且一次只能设置其中一个字段 而没有太多冗余 例如文件系统 假设我们有一张包含驱动器的表 一张包含文件夹 一张包含文件 驱动器和文件非常简单 但是 文件夹有一个父级 它可以是文件夹
  • 从存储过程 Transact-SQL SQL Server 中访问结果集

    我正在使用 SQL Server 2005 我想知道如何从 transact sql 中访问不同的结果集 以下存储过程返回两个结果集 例如 如何从另一个存储过程访问它们 CREATE PROCEDURE getOrder orderId a
  • Java中静态初始化和动态初始化有什么区别? [复制]

    这个问题在这里已经有答案了 最近在LeetCode上做一些练习时 我发现了一些技巧解决方案 它使用一个Object o来引用一个数组Object o new Object null null 我想也许是因为在java中一切都是对象 但是当我
  • 从“void*”到非“void”指针的转换需要显式强制转换(第 17 行)

    我正在阅读 Learn C the Hard Way 一书 当我尝试运行这个程序时 我收到以下错误消息 从 void 到非 void 指针的转换需要显式强制转换 我不知道如何解决这个问题 我是否必须更改结构中的返回变量 不管怎样 看一下 这
  • 为 Postgres 函数设置默认返回值

    我在 Postgres 中有以下功能 CREATE OR REPLACE FUNCTION point total user id integer gametime date RETURNS bigint AS BODY SELECT su
  • Python urllib urlencode 问题与æøå

    如何对带有特殊字符的字符串进行 urlencode ex urllib urlencode http www test com q test 我收到此错误 不是有效的非字符串序列或 映射对象 urlencode旨在获取字典 例如 gt gt
  • 消息:过时的元素引用:元素未附加到 Python 中的页面文档

    我一直在尝试在三个不同的网络链接中运行以下代码 代码在一个网络链接上运行良好 但是 它会抛出有关 消息 过时的元素引用 元素未附加到页面文档 的错误消息 我查看了论坛之前的两个主题 Python Selenium 过时元素修复 and 如何
  • 我的机器上 OpenCV 算法的 GPU 版本比 CPU 版本慢?

    在尝试使用 GPU 和 OpenCV 来加速简单算法时 我注意到在我的机器 Ubuntu 12 10 NVidia 9800GT Cuda 4 2 9 g 4 7 2 上 GPU 版本实际上比 CPU 版本慢 我用下面的代码进行了测试 in