我有一个[32678 x 10]矩阵(w2c
),我想将其中的24700行复制到另一个矩阵(out
)。我有要在向量( index
)中复制的行的索引。为了在 matlab 中执行此操作,我这样做:
out = w2c(index_im,:);
大约需要 0.002622 秒。
在 OpenCV 中:
Mat out(index.cols, w2c.cols, w2c.type());
for (int i = 0; i < index.cols; ++i) {
w2c.row(index.at<int>(i) - 1).copyTo(out.row(i));
}
大约需要 0.015121 秒。
如您所见,Matlab 的速度提高了 6 倍。如何使OpenCV代码高效?
我正在使用cmake-2.9,g ++ -4.8,opencv-2.4.9,ubuntu 14.04
更新:
我在发布模式下运行我的代码,这是结果(它仍然比 Matlab 慢得多)
RELEASE DEBUG MATLAB
0.008183 0.010070 0.001604
0.009630 0.010050 0.001679
0.009120 0.009890 0.001566
0.007534 0.009567 0.001635
0.007886 0.009886 0.001840
根据我们在聊天中的讨论,您没有在启用优化的情况下进行编译。如果这样做,您将看到显着的性能提升。此外,请确保您正在链接到OpenCV的发布版本。
我在未启用优化和启用优化的情况下测量了以下示例的执行时间:
主.cpp
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <random>
#include <vector>
#include <chrono>
#include <opencv2/opencv.hpp>
int main(int argc, char **argv)
{
const int num_rows = 32678;
const int num_cols = 10;
const int index_size = 24700;
const int num_runs = 1000;
const int seed = 42;
std::vector<int> index_vec(num_rows);
// fill index with sequence
std::iota (index_vec.begin(), index_vec.end(), 0);
// randomize sequence
std::random_device rd;
std::mt19937 g(rd());
g.seed(seed);
std::shuffle(index_vec.begin(), index_vec.end(), g);
// trunkate index
index_vec.resize(index_size);
cv::Mat w2c(num_rows, num_cols, CV_32F);
// copy
cv::Mat out(index_size, w2c.cols, w2c.type());
auto start = std::chrono::high_resolution_clock::now();
for (int k = 0; k<num_runs; ++k)
{
for (int i = 0; i < index_size; ++i)
{
w2c.row(index_vec[i]).copyTo(out.row(i));
}
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << duration.count()/num_runs << " microseconds" << std::endl;
return 0;
}
CMakeList.txt
project(copy)
find_package(OpenCV REQUIRED)
add_executable(copy main.cpp)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(copy ${OpenCV_LIBS})
无需优化即可编译和运行
cmake . -DCMAKE_BUILD_TYPE=DEBUG
make
./copy
3924 microseconds
通过优化进行编译和运行
cmake . -DCMAKE_BUILD_TYPE=RELEASE
make
./copy
2664 microseconds
我运行了这些测试
- 英特尔酷睿 i7-4600U 处理器
- 乌班图14.04(x64)
- 海湾合作委员会 4.8.2
- OpenCV 3.0.0 (发布版本)
所以我尝试了不同的方法来解决这个问题,而获得比 Matlab 更好的性能的唯一方法是使用memcpy
并直接自己复制数据。
Mat out( index.cols, w2c.cols, w2c.type() );
for ( int i=0;i<index.cols;++i ){
int ind = index.at<int>(i)-1;
const float *src = w2c.ptr<float> (ind);
float *des = out.ptr<float> (i);
memcpy(des,src,w2c.cols*sizeof(float));
}
这样,整个过程大约花费了 0.001063,比 Matlab 快一点。
我还发现以这种方式复制数据:
Mat out;
Mat out( index.cols, w2c.cols, w2c.type() );
for ( int i=0;i<index.cols;++i ){
int ind = index.at<int>(i)-1;
out.push_back(w2c.row(ind));
}
比像这样复制它更快:
Mat out( index.cols, w2c.cols, w2c.type() );
for ( int i=0;i<index.cols;++i ){
int ind = index.at<int>(i)-1;
w2c.row(ind).copyTo(out.row(i));
}
但我不知道为什么。无论如何,它们都比Matlab慢。