为什么Opencv GPU代码比CPU慢
Why Opencv GPU code is slower than CPU?
我正在笔记本上使用opencv242+VS2010
我试着在OpenCV中对GPU块进行一些简单的测试,但它显示GPU比CPU代码慢100倍。在这段代码中,我只是将彩色图像转换为灰度图像,使用cvtColor的功能
这是我的代码,PART1是CPU代码(测试CPU RGB2GRAY),PART2是上传图像到GPU,PART3是GPU RGB2GRAY,PART4又是CPU RGB2GRAY。有三件事让我很好奇:
1在我的代码中,part1是0.3ms,而part4(与part1完全相同)是40ms
2将图像上传到GPU的第二部分是6000ms
3第3部分(GPU代码)是11ms,对于这个简单的图像来说太慢了!
#include "StdAfx.h"
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/gpu/gpumat.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <ctime>
#include <windows.h>
using namespace std;
using namespace cv;
using namespace cv::gpu;
int main()
{
LARGE_INTEGER freq;
LONGLONG QPart1,QPart6;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&freq);
dfFreq = (double)freq.QuadPart;
cout<<getCudaEnabledDeviceCount()<<endl;
Mat img_src = imread("d:\CUDA\train.png", 1);
// PART1 CPU code~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// From color image to grayscale image.
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
Mat img_gray;
cvtColor(img_src,img_gray,CV_BGR2GRAY);
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("CPU RGB2GRAY running time is %.2f msnn",dfTim);
// PART2 GPU upload image~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpuMat gimg_src;
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
gimg_src.upload(img_src);
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("Read image running time is %.2f msnn",dfTim);
GpuMat dst1;
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
/*dst.upload(src_host);*/
dst1.upload(imread("d:\CUDA\train.png", 1));
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("Read image running time 2 is %.2f msnn",dfTim);
// PART3~ GPU code~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// gpuimage From color image to grayscale image.
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
GpuMat gimg_gray;
gpu::cvtColor(gimg_src,gimg_gray,CV_BGR2GRAY);
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("GPU RGB2GRAY running time is %.2f msnn",dfTim);
// PART4~CPU code(again)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// gpuimage From color image to grayscale image.
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
Mat img_gray2;
cvtColor(img_src,img_gray2,CV_BGR2GRAY);
BOOL i_test=QueryPerformanceCounter(&freq);
printf("%d n",i_test);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("CPU RGB2GRAY running time is %.2f msnn",dfTim);
cvWaitKey();
getchar();
return 0;
}
上面的大多数答案实际上都是错误的。它慢20.000倍的原因当然不是因为"CPU时钟速度更快"answers"它必须将其复制到GPU"(公认的答案)。这些都是因素,但如果说你忽略了一个事实,即你对一个令人厌恶的平行问题有更大的计算能力。说20000倍的性能差异是因为后者太荒谬了。这里的作者知道有些不对劲,这不是直截了当的。解决方案:
您的问题是CUDA需要初始化它总是为第一张图像初始化,通常需要1-10秒,这取决于木星和火星的排列。现在试试这个。执行两次计算,然后对两者进行计时。在这种情况下,你可能会看到速度在马努特的同一个数量级内,而不是20000倍,这太荒谬了。你能对这个初始化做点什么吗?不,我不知道。这是个障碍。
编辑:我刚刚重读了这篇文章。你说你在笔记本上跑步。这些通常都有破旧的GPU,CPU有一个公平的涡轮。
cvtColor并没有做太多的工作,要使灰色化,只需要平均三个数字。
CPU上的cvColor代码使用SSE2指令一次处理多达8个像素,如果你有TBB,它使用所有核心/超线程,CPU的运行速度是GPU的10倍,最后你不必将数据复制到GPU上再复制回来。
尝试运行多次。。。。
-----------摘录自http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ性能
为什么第一个函数调用很慢?
这是因为初始化开销。在第一个GPU函数调用上,Cuda Runtime API被隐式初始化。此外,一些GPU代码是为您的视频卡在第一次使用时编译的(实时编译)。因此,为了衡量性能,有必要进行伪函数调用,然后再进行时间测试。
如果应用程序只运行一次GPU代码至关重要,则可以使用在多次运行中持久存在的编译缓存。有关详细信息,请阅读nvcc文档(CUDA_DEVCODE_CACHE环境变量)。
cvtColor是一个小操作,主机(CPU)和设备(GPU)之间的内存传输时间远远超过了在GPU上执行此操作所带来的任何性能提升。最小化这种内存传输的延迟是任何GPU计算的主要挑战。
你有什么GPU?
检查计算兼容性,也许是原因。
https://developer.nvidia.com/cuda-gpus
这意味着对于具有CC 1.3和2.0二进制图像的设备准备运行。对于所有较新的平台,1.3的PTX代码是JIT’ed转换为二进制图像。对于具有CC 1.1和1.2的设备,1.1的PTX为JIT’ed。对于CC 1.0的设备,没有可用的代码函数抛出异常。对于JIT编译所在的平台首先执行,运行缓慢。
http://docs.opencv.org/modules/gpu/doc/introduction.html
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- TensorFlow CPU 和 CUDA 代码共享
- 为什么当从面向任何 CPU 的 C# 项目调用此代码时,此代码会引发 System.AccessViolationExc
- 维护/维持两个代码集的风险,一个用于 CPU,一个用于 GPU,需要执行非常相似的功能
- 从 C++11 代码中获取系统内存和 CPU 使用率
- C++代码只能针对特定的 CPU 体系结构进行编译.有没有办法将其编译为所有架构
- 任何可以在单个 CPU 指令中在 0 和 1 之间翻转位/整数/布尔值的可能代码
- 代码执行/CPU 速度每 2 秒减慢一次
- 为什么 OpenMP 在这个 fft 代码中停留在 10% 的 CPU 消耗?
- 为什么GTX Titan上的Cublas比单线螺纹CPU代码慢
- 测量C 代码的CPU周期
- 为什么Opencv GPU代码比CPU慢
- 在CPU上使用OpenCL将一个数组复制到另一个数组比C++代码慢得多
- 是否可以计算出有多少 CPU 和 RAM 使用代码块
- 如何计算C++代码段的 CPU 周期成本
- GPU 调用后,CPU 代码运行缓慢
- 可视化设置一个c++应用程序使用最大CPU使用率,在代码中
- gcc/C++:如果CPU负载很低,那么代码优化用处不大,这是真的
- 使用 CUDA 计算积分图像比 CPU 代码慢