【问题标题】:Why function first-time calling costs much more time than the second time calling it and third and so on?为什么函数第一次调用比第二次和第三次调用花费更多的时间等等?
【发布时间】:2017-10-09 01:22:21
【问题描述】:

这是我基于 OpenCV 的代码:

int main()
{
    clock_t start, stop;
    Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);
    img.convertTo(img, CV_32F, 1.0);
    float *imgInP = (float *)img.data;    // get the input data point 
    Mat imgOut = Mat::zeros(Size(img.rows, img.cols), CV_32F);   // create output mat
    float *imgOutP = (float *)imgOutP.data;  // get the output data point

    // test several calling of opencv boxFilter
    start = clock();
    //blur(img, imgOut, Size(31, 31));
    boxFilter(img, imgOut, CV_32F, Size(31, 31));
    stop = clock();
    cout << "BoxFilter on OpenCV 1 : " << 1000.0 * (stop - start) / CLOCKS_PER_SEC << " ms" << endl;
    start = clock();
    //blur(img, imgOut, Size(31, 31));
    boxFilter(img, imgOut, CV_32F, Size(31, 31));
    stop = clock();
    cout << "BoxFilter on OpenCV 2 : " << 1000.0 * (stop - start) / CLOCKS_PER_SEC << " ms" << endl;
     start = clock();
    //blur(img, imgOut, Size(31, 31));
    boxFilter(img, imgOut, CV_32F, Size(31, 31));
    stop = clock();
    cout << "BoxFilter on OpenCV 3 : " << 1000.0 * (stop - start) / CLOCKS_PER_SEC << " ms" << endl;

    return 0;
}

这是上述程序的输出:

OpenCV 1 上的 BoxFilter:72.368ms

OpenCV 2 上的 BoxFilter:0.495 毫秒

OpenCV 3 上的 BoxFilter:0.403 毫秒

为什么第一次调用 boxFilter 所花费的时间(72.368 毫秒)比第二次(0.495 毫秒)和第三次(0.403 毫秒)要多得多

更重要的是,如果我在第三次调用 boxFilter 时更改输入图像,输出也不会改变。所以,可能不是图片数据缓存的因素……

感谢您的建议。

我的系统是 Ubuntu 14.04,i5-4460,12GB RAM,OpenCV 版本:3.1,cmake 版本:3.2,g++ 版本:4.8.4

下面是我的 cmake 文件:

cmake_minimum_required(VERSION 3.7)
project(boxfilterTest)

set(CMAKE_CXX_STANDARD 11)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

set(SOURCE_FILES main.cpp)
add_executable(boxfilterTest ${SOURCE_FILES})

target_link_libraries(boxfilterTest ${OpenCV_LIBS})

IDE 是 CLion。

【问题讨论】:

  • 一个词:缓存。
  • 抱歉再问一个问题,谁的缓存?指令缓存还是数据缓存?当我第三次调用boxFilter更改输入图像数据时,结果没有任何变化,时间也比第一次调用要小很多。
  • 也许它会生成运行时代码?您可以通过执行另一个类似的过滤器来检查这一点,例如 30x31。
  • 倒霉...,我把过滤器大小从 {31, 31} 改成了 {15, 15},还是不行...

标签: c++ function opencv time


【解决方案1】:

差异的原因是时序是由于指令缓存和数据缓存。可以通过强制将矩阵重新分配到不同的大小(例如调整图像大小)来验证数据缓存。如果在对boxFilter 的不同调用之间调整图像大小,则boxFilter 调用的执行时间会变得非常接近。这是演示上述现象的示例代码。

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

using namespace std;
using namespace cv;

int main()
{
    clock_t start, stop;
    Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);
    img.convertTo(img, CV_32F, 1.0);
    float *imgInP = (float *)img.data;    // get the input data point 
    Mat imgOut = Mat::zeros(Size(img.rows, img.cols), CV_32F);   // create output mat
    float *imgOutP = (float *)imgOut.data;  // get the output data point

    // test several calling of opencv boxFilter
    start = clock();
    //blur(img, imgOut, Size(31, 31));
    boxFilter(img, imgOut, CV_32F, Size(31, 31));
    stop = clock();

    cv::resize(img, img, cv::Size(), 1.1, 1.1); //Force data re-allocation

    cout << "BoxFilter on OpenCV 1 : " << 1000.0 * (stop - start) / CLOCKS_PER_SEC << " ms" << endl;
    start = clock();
    //blur(img, imgOut, Size(31, 31));
    //GaussianBlur(img, imgOut, Size(31, 31), 0.5);
    boxFilter(img, imgOut, CV_32F, Size(31, 31));
    stop = clock();

    cv::resize(img, img, cv::Size(), 0.909, 0.909);  //Force data re-allocation

    cout << "BoxFilter on OpenCV 2 : " << 1000.0 * (stop - start) / CLOCKS_PER_SEC << " ms" << endl;
     start = clock();
    //blur(img, imgOut, Size(31, 31));
    boxFilter(img, imgOut, CV_32F, Size(31, 31));
    stop = clock();
    cout << "BoxFilter on OpenCV 3 : " << 1000.0 * (stop - start) / CLOCKS_PER_SEC << " ms" << endl;

    return 0;
}

程序输出:

无需重新分配数据:

OpenCV 1 上的 BoxFilter:2.459 毫秒

OpenCV 2 上的 BoxFilter:1.599 毫秒

OpenCV 3 上的 BoxFilter:1.568 毫秒

数据重新分配:

OpenCV 1 上的 BoxFilter:2.225 毫秒

OpenCV 2 上的 BoxFilter:2.368 毫秒

OpenCV 3 上的 BoxFilter:2.091 毫秒

【讨论】:

  • 这并不能解释第一次调用 OP 时的 72 毫秒延迟。一定有其他的影响,因为 70 毫秒是一个很长的时间。
  • 感谢您的回复。但是,我想知道为什么第一次调用也要花费这么多时间。我已将编译器从“nvcc”更改为“g++”,但看起来这不是确切的因素。再次感谢您的建议。
【解决方案2】:

嗯,我想可能是指令缓存造成的(毕竟CPU中有*MB L2缓存)。但我不知道如何验证和改进它。

【讨论】:

  • 你能分享你运行代码的系统的规格吗?此外,OpenCV 的编译方式也是观察到的执行速度的决定因素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多