c++ - 从文件中并行读取图像
问题描述
我有这个函数从数据集中读取负图像(大约 122000)
void load_images(const String & dirname, vector< Mat > & img_lst, bool showImages = false)
{
vector< String > files;
glob(dirname, files);
for (size_t i = 0; i < files.size(); ++i)
{
Mat img = imread(files[i]); // preia imagine
if (img.empty()) // treci peste daca este imagine invalida
{
cout << files[i] << " is invalid!" << endl;
continue;
}
if (showImages)
{
imshow("image", img);
waitKey(1);
}
img_lst.push_back(img);
}
}
并且需要大量时间来处理,有时它会被阻止。如何优化它并使其并行?
解决方案
我稍微更改了您的代码以使用 OpenMP 来并行加载 - 实际更改很小 - 我只是pragma
在循环之前放置了一个 OpenMPfor
并序列化访问图像矢量,因为矢量不是线程安全的。
#include <iostream>
#include <vector>
#include <mutex>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void load_images(int start,int end){
vector<Mat>img_lst;
mutex mtx;
#pragma omp parallel for
for(size_t i=start;i<=end;i++){
char filename[16];
sprintf(filename,"%d.jpg",i);
Mat img = imread(filename);
if (img.empty()){
cerr << "ERROR: Failed to load " << filename << endl;
}
mtx.lock();
img_lst.push_back(img);
mtx.unlock();
}
mtx.lock();
cout << "INFO: Loaded " << img_lst.size() << endl;
mtx.unlock();
}
int
main(int argc,char*argv[])
{
load_images(1,122000);
}
您可以像这样控制线程数:
export OMP_NUM_THREADS=2
time ./main
加载 122,000 张图像的时间根据我使用的线程数而有所不同,如下表所示:
Threads Time (s)
================
1 44
2 23
4 12.4
8 8.8
然后我决定,如果您经常这样做以关心,您可能希望预先支付一小笔费用以进一步改善时间。因此,您可能希望将图像一次转换为更简单的读取格式,而不是执行所有 CPU 密集型代码来解压缩 JPEG,例如PNM。因此,我使用GNU Parallel将所有 JPEG 图像转换为 PNM ,然后加载 PNM 图像:
所以看起来像:
seq 122000 | parallel convert {}.jpg {}.pnm
代码是:
...
...
#pragma omp parallel for
for(size_t i=start;i<=end;i++){
char filename[16];
sprintf(filename,"%d.pnm",i); <--- ONLY LINE CHANGED
Mat img = imread(filename);
...
...
你可以看到时间要短得多:
Nthreads Time(s)
================
1 7
2 4
4 2.5
8 3.2
要使用 OpenMP 进行编译,请使用:
g++ -fopenmp =O3 -march native ...
推荐阅读
- allure - 无需在系统 Allure 命令行工具中安装即可生成魅力报告
- php - 如何在 sh 文件 30 分钟后停止 PHP cron 作业
- android - Google Books API 返回意外的缩略图 URL
- ruby - rspec 在程序退出时退出
- python - 如何用 pandas 读取合并的单元格(xls,xlsx)?
- c# - HashSet:推断正确的 EqualityComparer
。默认? - c# - 当应用程序在 docker 容器中运行时,ASP.NET API 中的 MSAL .NET 设备代码身份验证不起作用
- php - PHP数组插入表取决于每个数组
- scala - 如何在胖罐子依赖中遮蔽包裹
- javascript - 如何将甜甜圈的 svg 添加到每个节点以代替径向树图中的圆圈