本质上,我正在使用OpenCV的OpenCL过滤器对OpenGL帧缓冲区进行后处理。一目了然,通过鼠标交互,一切都可以实时流畅,流畅地运行。但是,当我渲染一个稳定的场景时(即该进程应该处于空闲状态时),我意识到单核CPU的使用率很高,这潜在地跟随了最后一次交互几秒钟甚至半分钟。实际上,CPU的使用率一直存在,但不是在“我的”线程中(因此它不会阻塞任何东西),而是在NVidia的nvopencl.dll中在后台运行。
我的系统是:
Windows 10 64-bit
Intel Core i7-6820HQ
NVidia Quadro M4000M
nvopencl.dll as NVidia CUDA 9.0.176 OpenCL 1.2 Driver
Visual Studio 2015
我自己构建了OpenCV,没有OpenCV,该问题也可以重现,只是使复制变得更容易。要复制所有代码,将需要大量代码,但我设法将其包装如下。 (当然,该示例没有显示是否完成了任何图像过滤,但是在实际应用中,我可以轻松地验证每次finish
调用之后确实发生了这种情况):
#include <windows.h>
#include <iostream>
#include <thread>
#include "opencv2/core.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
// Retrieves timing information for the specified process.
// millisecond units like GetTickCount()
double GetProcessTickCount(void )
{
FILETIME c, e, k, u;
GetProcessTimes(GetCurrentProcess(),&c,&e,&k,&u);
ULARGE_INTEGER a,b;
a.LowPart = k.dwLowDateTime;
a.HighPart = k.dwHighDateTime;
b.LowPart = u.dwLowDateTime;
b.HighPart = u.dwHighDateTime;
double t = 1000.0 * (double)( a.QuadPart + b.QuadPart ) * 100.0e-9;
return t;
}
int main( void )
{
// read any image file
cv::Mat src = cv::imread("face1.png",cv::IMREAD_COLOR);
std::cout << "Image size: "<< src.size() << std::endl;
#if 0
cv::Mat dst;
cv::ocl::setUseOpenCL(false); // explicit not to use OpenCL
std::cout << "Without OpenCL" << std::endl;
double t = cv::getTickCount();
for ( int i=0;i<500;++i )
{
cv::bilateralFilter( src, dst, 15, 32.0, 8.0 );
}
#else
// copy into a UMat
cv::UMat u, d;
src.copyTo( u );
// force using OpenCL
cv::ocl::setUseOpenCL(true);
double t = cv::getTickCount();
for ( int i=0;i<500;++i )
{
// do bilateral filtering (on OpenCL, verify this by the debugger)
cv::bilateralFilter( u, d, 15, 32.0, 8.0 );
// finish the work
cv::ocl::finish();
// render the result, the finish is not required, but with OpenGL texture objects it kinda was...
// ...
}
#endif
t = cv::getTickCount()-t;
std::cout << "t=" << (t/cv::getTickFrequency()) << " seconds, fps=";
std::cout << 500.0/(t/cv::getTickFrequency()) << std::endl;
double cpuTime = 0;
t = cv::getTickCount(); // wait time starts
for ( ; ; std::this_thread::sleep_for( std::chrono::seconds(1) ) )
{
double time = GetProcessTickCount();
// once we figure out CPU no more working on this process, we finish
// !! note, first 1 second wait happens anyway
if ( time - cpuTime > 2.0 ) // 2 ms to play safe
{
cpuTime = time;
}else
break;
}
t = cv::getTickCount()-t; // wait time ends
std::cout << "about to exit after waiting " << (t/cv::getTickFrequency()) << " seconds" << std::endl;
return 0;
}
这里是带有印刷品
Image size: [640 x 960]
t=2.78591 seconds, fps=179.474
about to exit after waiting 21.0132 seconds
Press any key to continue . . .
并且没有OpenCL
Image size: [640 x 960]
Without OpenCL
t=10.9039 seconds, fps=45.8551
about to exit after waiting 1.00018 seconds
Press any key to continue . . .
当然,问题是如何解决此问题?
*更新*
我无法在带有Intel i5-8250U和Intel OpenCL驱动程序的移动平台上重现此问题。请注意,等待时间为预期的1秒。看起来像是NVidia问题。
Image size: [640 x 960]
[ INFO:0] Initialize OpenCL runtime...
[ INFO:0] Preparing OpenCL cache configuration for context: Intel_R__Corporation--Intel_R__UHD_Graphics_620--23_20_16_4849
t=8.36944 seconds, fps=59.7411
about to exit after waiting 1.00269 seconds
Press any key to continue . . .
vs。
Image size: [640 x 960]
Without OpenCL
t=39.0353 seconds, fps=12.8089
about to exit after waiting 1.00778 seconds
Press any key to continue . . .
该问题已被问过,但尚未解决 Unexpected CPU utilization with OpenCL